1 3 4 1 1 5 2 3 1 3 3 3 1 1
5/4
考虑每一个点,对结果的影响,如果,一个点包括了x个区间,那么,就有C(x,3)个w[i]在分子上,分母为C(m,3);所以最终的问题就是要求每个点,所点的区间数,真接用区间的开头加1,结尾减1,复杂度为o(n ),如果用线段树成段更新,复杂度为o(n * log(n);注意不要爆了long long,所以分子分母先都除上6.
第一种方法
#define N 300005 #define M 100005 #define maxn 205 #define SZ 26 #define MOD 1000000000000000007 #define lson (now<<1) #define rson (now<<1|1) int n,T,m,w[N],a,b,num[N],pri[N][2]; int main() { while(S(T)!=EOF) { while(T--){ S2(n,m); For(i,1,n+1){ scan_d(a); w[i] = a; num[i] = 0; pri[i][0] = pri[i][1] = 0; } FI(m){ scan_d(a);scan_d(b); pri[a][0]++; pri[b][1]++; } int nn = 0; for(int i = 1;i<=n;i++){ nn += pri[i][0]; num[i] = nn; nn -= pri[i][1]; } ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6; For(i,1,n+1){ ll t = (ll) num[i]; if(t >= 3){ ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6; } } if(ans == 0){ printf("%lld\n",ans); continue; } ll gc = gcd(ans,s2); ans /= gc;s2 /= gc; if(s2 == 1) printf("%lld\n",ans); else printf("%lld/%lld\n",ans,s2); } } //fclose(stdin); //fclose(stdout); return 0; }
第二种方法(线段树)
#define N 300005 #define M 100005 #define maxn 205 #define SZ 26 #define MOD 1000000000000000007 #define lson (now<<1) #define rson (now<<1|1) int n,T,m,w[N],a,b; struct node{ int sum; }; node tree[N*4]; void pushDown(int now){ if(tree[now].sum > 0){ tree[lson].sum += tree[now].sum; tree[rson].sum += tree[now].sum; tree[now].sum = 0; } } void buildTree(int l,int r,int now){ tree[now].sum = 0; if(l >= r){ return ; } int mid = (l+r)>>1; buildTree(l,mid,lson); buildTree(mid+1,r,rson); } void updateTree(int l,int r,int now,int s,int e,int c){ if(s <= l && e>= r){ tree[now].sum += c; return ; } pushDown(now); int mid = (l+r)>>1; if(s <= mid) updateTree(l,mid,lson,s,e,c); if(e > mid) updateTree(mid+1,r,rson,s,e,c); } int queryTree(int l,int r,int now,int s,int e){ if(s <= l && e>= r){ return tree[now].sum; } pushDown(now); int mid = (l+r)>>1; if(s <= mid) return queryTree(l,mid,lson,s,e); if(e > mid) return queryTree(mid+1,r,rson,s,e); return 0; } int main() { while(S(T)!=EOF) { while(T--){ S2(n,m); buildTree(1,n,1); For(i,1,n+1){ scan_d(a); w[i] = a; } FI(m){ scan_d(a);scan_d(b); updateTree(1,n,1,a,b,1); } ll ans = 0,s2 = (ll)(m) * (ll)(m - 1) * (ll)(m -2) / 6; For(i,1,n+1){ ll t = (ll) queryTree(1,n,1,i,i); if(t >= 3){ ans += (ll)t * (ll)(t - 1) * (ll)(t - 2) * (ll)w[i] / 6; } } if(ans == 0){ printf("%lld\n",ans); continue; } ll gc = gcd(ans,s2); ans /= gc;s2 /= gc; if(s2 == 1) printf("%lld\n",ans); else printf("%lld/%lld\n",ans,s2); } } //fclose(stdin); //fclose(stdout); return 0; }