UOJ#58. 【WC2013】糖果公园
学了一波树上莫队
想要自己YY出转移方法交代了一个晚修未遂。。
现在的做法相当于是维护两条链,lca即用即删,好妙啊。。
对于树分块,写的是[B,3B]的,看到有人写伪ETT括号序列的,不知道那个快呢。。。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; const int maxn=110000; const int maxm=110000; const int maxQ=110000; struct node { int x,y,next; }a[maxn*2];int len,last[maxn]; void ins(int x,int y) { len++; a[len].x=x;a[len].y=y; a[len].next=last[x];last[x]=len; } int block,z,st[maxn]; int top,sta[maxn]; int Bin[30],f[30][maxn],dep[maxn]; void dfs(int x) { for(int i=1;Bin[i]<=dep[x];i++)f[i][x]=f[i-1][f[i-1][x]]; int now=top; for(int k=last[x];k;k=a[k].next) { int y=a[k].y; if(y!=f[0][x]) { f[0][y]=x; dep[y]=dep[x]+1; dfs(y); if(top-now>=block) { z++; while(top!=now)st[sta[top--]]=z; } } } sta[++top]=x; } int LCA(int x,int y) { if(dep[x]<dep[y])swap(x,y); for(int i=25;i>=0;i--) if(dep[x]-dep[y]>=Bin[i])x=f[i][x]; if(x==y)return x; for(int i=25;i>=0;i--) if(dep[x]>=Bin[i]&&f[i][x]!=f[i][y])x=f[i][x],y=f[i][y]; return f[0][x]; } //-----------------------------split---------------------------------------------------------------------- struct Change{int x,nc,pc,t;}c[maxQ];int clen,clast[maxn]; struct Query{int x,y,t;}q[maxQ];int qlen;LL as[maxQ]; bool cmp(Query q1,Query q2) { return st[q1.x]==st[q2.x]? (st[q1.y]==st[q2.y]?q1.t<q2.t:st[q1.y]<st[q2.y]) : st[q1.x]<st[q2.x]; } LL sum; int co[maxn],s[maxn];//节点颜色,节点是否计入答案 LL num[maxm],v[maxm],w[maxn];//当前颜色出现次数,某颜色的价值,新奇指数 void change(int x,int col) { if(s[x]) sum-=w[num[co[x]]]*v[co[x]], num[co[x]]--; co[x]=col; if(s[x]) num[co[x]]++, sum+=w[num[co[x]]]*v[co[x]]; } void res(int x) { if(!s[x]) num[co[x]]++, sum+=w[num[co[x]]]*v[co[x]]; else sum-=w[num[co[x]]]*v[co[x]], num[co[x]]--; s[x]^=1; } void zzz(int x,int y) { while(x!=y) { if(dep[x]>dep[y])res(x),x=f[0][x]; else res(y),y=f[0][y]; } } void solve(int Q) { int j=0; sum=0; q[0].x=q[0].y=1; for(int i=1;i<=qlen;i++) { while(j<clen&&c[j+1].t<q[i].t)j++,change(c[j].x,c[j].nc); while(j>0&&q[i].t<c[j].t)change(c[j].x,c[j].pc),j--; zzz(q[i-1].x,q[i].x); zzz(q[i-1].y,q[i].y); int lca=LCA(q[i].x,q[i].y); res(lca); as[q[i].t]=sum; res(lca); } } //-----------------------------莫队---------------------------------------------------------------------- int main() { int n,m,Q; scanf("%d%d%d",&n,&m,&Q); for(int i=1;i<=m;i++)scanf("%lld",&v[i]); for(int i=1;i<=n;i++)scanf("%lld",&w[i]); int x,y; len=1; for(int i=1;i<n;i++) { scanf("%d%d",&x,&y); ins(x,y),ins(y,x); } block=pow(x,2.0/3.0); Bin[0]=1;for(int i=1;i<=25;i++)Bin[i]=Bin[i-1]*2; z=0;dfs(1); z++;while(top!=0)st[sta[top--]]=z; for(int i=1;i<=n;i++) scanf("%d",&co[i]),clast[i]=co[i]; int op=0; for(int i=1;i<=Q;i++) { scanf("%d",&op); if(op==0) { clen++; scanf("%d%d",&c[clen].x,&c[clen].nc),c[clen].t=i; c[clen].pc=clast[c[clen].x],clast[c[clen].x]=c[clen].nc; } else { qlen++; scanf("%d%d",&q[qlen].x,&q[qlen].y),q[qlen].t=i; } } sort(q+1,q+qlen+1,cmp); memset(as,-1,sizeof(as)); solve(Q); for(int i=1;i<=Q;i++) if(as[i]!=-1)printf("%lld\n",as[i]); return 0; }
pain and happy in the cruel world.