莫队算法
#include<cstdio> #include<cmath> #include<algorithm> using namespace std; long long lm,rm; long long c[50001],a[50001]; long long t1,t2; long long ans; struct data{ long long l,r,key1,num; }q[50001]; struct str{ long long s,m; }an[50001]; bool comp(const data &a, const data &b){ if (a.key1<b.key1) return(1); if (a.key1>b.key1) return(0); if (a.r<b.r) return(1); return(0); } long long gcd(long long a,long long b){ if (a%b==0) return(b);else return(gcd(b,a%b)); } void movel(long long targ){ if (lm<targ) for (;lm<targ;){ ans=ans-c[a[lm]]*(c[a[lm]]-1)+(c[a[lm]]-1)*(c[a[lm]]-2); c[a[lm]]--; lm++; } if (lm>targ) for (;lm>targ;){ lm--; ans=ans-c[a[lm]]*(c[a[lm]]-1)+c[a[lm]]*(c[a[lm]]+1); c[a[lm]]++; } } void mover(long long targ){ if (rm<targ) for (;rm<targ;){ rm++; ans=ans-c[a[rm]]*(c[a[rm]]-1)+(c[a[rm]]+1)*c[a[rm]]; c[a[rm]]++; } if (rm>targ) for (;rm>targ;){ ans=ans-c[a[rm]]*(c[a[rm]]-1)+(c[a[rm]]-1)*(c[a[rm]]-2); c[a[rm]]--; rm--; } } int main(){ long long n,m; scanf("%lld%lld",&n,&m); int siz=int(sqrt(n)); for (long long i=1;i<=n;i++) scanf("%lld",&a[i]); for (long long i=1;i<=m;i++) { scanf("%lld%lld",&q[i].l,&q[i].r); q[i].key1=q[i].l/siz; q[i].num=i; } sort(q+1,q+m+1,comp); lm=1,rm=0; ans=0; for (long long i=1;i<=m;i++){ movel(q[i].l);mover(q[i].r); t1=ans;t2=(rm-lm+1)*(rm-lm); if (t1!=0){ long long gc=gcd(t1,t2); an[q[i].num].s=t1/gc;an[q[i].num].m=t2/gc; } else { an[q[i].num].s=0;an[q[i].num].m=1; } } for (int i=1;i<=m;i++) printf("%lld/%lld\n",an[i].s,an[i].m); }
BZOJ2038 小Z的袜子
_________________________________________________________
带修改莫队与树上莫队
Codechef FEB17 DISTNUM3
#include <bits/stdc++.h> using namespace std; int brac[500001][2],lis[500001],cnt,nd[500001],nxt[1000001],des[1000001]; int dep[500001],fa[500001][21],n,Q,ta[500001],a[500001],opt[500001][3]; int pre[500001],app[500001],ans,PO,L,R,inq[500001],blo,quecnt,fin[500001]; int scnt,getnxt[500001],getpre[500001]; struct data{ int num,orityp,ori; }tmp[500001]; int mycomp(const data&a,const data&b){ return(a.num<b.num); } struct ques{ int pos,l,r,ori; }que[500001]; int mycomp2(const ques&a,const ques&b){ if (a.pos/blo<b.pos/blo) return(1); if (a.pos/blo>b.pos/blo) return(0); if (a.l/blo<b.l/blo) return(1); if (a.l/blo>b.l/blo) return(0); return(a.r<b.r); } void addedge(int x,int y){ nxt[++scnt]=nd[x];des[scnt]=y;nd[x]=scnt; } void dfs(int po,int f=-1){ brac[po][0]=++cnt; lis[cnt]=po; for(int p=nd[po];p!=-1;p=nxt[p]) if (des[p]!=f){ dep[des[p]]=dep[po]+1; fa[des[p]][0]=po; dfs(des[p],po); } brac[po][1]=++cnt; lis[cnt]=po; } void initlca(){ for (int i=1;i<=20;i++) for (int j=1;j<=n;j++) fa[j][i]=fa[fa[j][i-1]][i-1]; } void initpre(){ memcpy(ta,a,sizeof(a)); for (int i=1;i<=Q;i++) if (opt[i][0]==2){ pre[i]=ta[opt[i][1]]; ta[opt[i][1]]=opt[i][2]; } } void edi(int po,int num){ app[po]+=num; if (app[po]==1&&num==1) ans++; if (app[po]==0&&num==-1) ans--; } void moverPO(){ PO=getnxt[PO]; if (opt[PO][0]==2){ edi(a[opt[PO][1]],(-1)*inq[opt[PO][1]]); a[opt[PO][1]]=opt[PO][2]; edi(a[opt[PO][1]],1*inq[opt[PO][1]]); } } void movelPO(){ if (opt[PO][0]==2){ edi(a[opt[PO][1]],(-1)*inq[opt[PO][1]]); a[opt[PO][1]]=pre[PO]; edi(a[opt[PO][1]],1*inq[opt[PO][1]]); } PO=getpre[PO]; } void moverR(){ R++; inq[lis[R]]^=1; edi(a[lis[R]],(inq[lis[R]] ? 1:-1)); } void movelR(){ inq[lis[R]]^=1; edi(a[lis[R]],(inq[lis[R]] ? 1:-1)); R--; } void moverL(){ inq[lis[L]]^=1; edi(a[lis[L]],(inq[lis[L]] ? 1:-1)); L++; } void movelL(){ L--; inq[lis[L]]^=1; edi(a[lis[L]],(inq[lis[L]] ? 1:-1)); } int getlca(int x,int y){ if (dep[x]<dep[y]) swap(x,y); for (int i=20;i>=0;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i]; for (int i=20;i>=0;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; if (x==y) return(x);else return(fa[x][0]); } void initlink(){ int lst=0; for (int i=1;i<=Q;i++) if (opt[i][0]==2){ getpre[i]=lst; lst=i; } getpre[Q+1]=lst; lst=Q+1; for (int i=Q;i>=1;i--) if (opt[i][0]==2){ getnxt[i]=lst; lst=i; } getnxt[0]=lst; } int main(){ scanf("%d%d",&n,&Q); for (int i=1;i<=n;i++) nd[i]=-1; for (int i=1;i<=n;i++){ cnt++; tmp[cnt].orityp=1;tmp[cnt].ori=i; scanf("%d",&tmp[cnt].num); } for (int i=1;i<n;i++){ int t1,t2; scanf("%d%d",&t1,&t2); addedge(t1,t2);addedge(t2,t1); } for (int i=1;i<=Q;i++){ scanf("%d%d%d",&opt[i][0],&opt[i][1],&opt[i][2]); if (opt[i][0]==2){ cnt++; tmp[cnt].orityp=2;tmp[cnt].ori=i; tmp[cnt].num=opt[i][2]; } } sort(tmp+1,tmp+cnt+1,mycomp); int p=0;tmp[0].num=-1e9; for (int i=1;i<=cnt;i++){ if (tmp[i].num!=tmp[i-1].num) p++; if (tmp[i].orityp==1) a[tmp[i].ori]=p;else opt[tmp[i].ori][2]=p; } cnt=0;dep[1]=1; dfs(1); initlca();initpre(); initlink(); blo=pow(4*n,2.0/3); for (int i=1;i<=Q;i++) if (opt[i][0]==1){ if (brac[opt[i][1]][0]>brac[opt[i][2]][0]) swap(opt[i][1],opt[i][2]); quecnt++; if (brac[opt[i][1]][1]>brac[opt[i][2]][0]) que[quecnt].l=brac[opt[i][1]][0], que[quecnt].r=brac[opt[i][2]][0];else que[quecnt].l=brac[opt[i][1]][1], que[quecnt].r=brac[opt[i][2]][0]; que[quecnt].pos=i; que[quecnt].ori=i; } sort(que+1,que+quecnt+1,mycomp2); L=1;R=0;PO=0; for (int i=1;i<=quecnt;i++){ while (getnxt[PO]<que[i].pos) moverPO(); while (PO>que[i].pos) movelPO(); while (R<que[i].r) moverR(); while (R>que[i].r) movelR(); while (L<que[i].l) moverL(); while (L>que[i].l) movelL(); fin[que[i].ori]=ans; int lc=getlca(opt[que[i].ori][1],opt[que[i].ori][2]); if ((lc!=opt[que[i].ori][1])&&(lc!=opt[que[i].ori][2])) if (!app[a[lc]]) fin[que[i].ori]++; } for (int i=1;i<=Q;i++) if (opt[i][0]==1) printf("%d\n",fin[i]); }