标签:c++ i++ def ace orb || scan lse ret
将询问排序分块后每块内部排序
然后每次左端点增减复杂度为√N,每块右端点增减N
每次问询复杂度√N+N
总共有√N次问询
#include <bits/stdc++.h> using namespace std; #define fore(i,a,b) for(int i=(int)(a);i<=(int)(b);i++) #define forb(i,a,b) for(int i=(int)(a);i>=(int)(b);i--) #define fir first #define sec second typedef long long ll; const int N=500010; int c[N],L[N],R[N],num[N]; struct node{int l,r,id;}q[N]; bool cmp(node a,node b){return a.l<b.l || (a.l==b.l && a.r<b.r);} bool cmp0(node a,node b){return a.r<b.r;} ll ans,anss[N][2],g; int T, n, m; void work(int x,int w){ans-=(ll)num[x]*(num[x]-1);num[x]+=w;ans+=(ll)num[x]*(num[x]-1);} ll gcd(ll a,ll b){return b?gcd(b,a%b):a;} void gcdab(ll &a,ll &b){g=gcd(a,b);if(!g) b=1; else a/=g,b/=g;} int main(){ cin>>n>>m; fore(i,1,n) scanf("%d",&c[i]); fore(i,1,m){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1,cmp); int t=sqrt(m); fore(i,1,t) L[i]=(i-1)*t+1,R[i]=i*t; if(R[t]<n) L[t+1]=R[t]+1,R[++t]=m; fore(i,1,t){ memset(num,0,sizeof(num)); sort(q+L[i],q+R[i]+1,cmp0); ans=0; int l=q[L[i]].l,r=q[L[i]].r; fore(j,l,r) work(c[j],1); anss[q[L[i]].id][0]=ans; anss[q[L[i]].id][1]=(ll)(r-l)*(r-l+1); gcdab(anss[q[L[i]].id][0],anss[q[L[i]].id][1]); fore(j,L[i]+1,R[i]){ while(r<q[j].r) work(c[++r],1); while(r>q[j].r) work(c[r--],-1); while(l<q[j].l) work(c[l++],-1); while(l>q[j].l) work(c[--l],1); if(q[j].l==q[j].r) anss[q[j].id][0]=0,anss[q[j].id][1]=1; else{ anss[q[j].id][0]=ans; anss[q[j].id][1]=(ll)(r-l)*(r-l+1); gcdab(anss[q[j].id][0],anss[q[j].id][1]); } } } fore(i,1,m) printf("%lld/%lld\n",anss[i][0],anss[i][1]); return 0; }
标签:c++ i++ def ace orb || scan lse ret
原文地址:https://www.cnblogs.com/rign/p/11102229.html