前言:
这次NOIP好像考不好就退役?
所以写点日记记录生活 好过什么都没留下 给以后做点怀念
2017.9.5
This Problem Is Too Simple! |
这个超好的题
只要你想到离散化 O(N2logN) 草过是没有什么毛病的
可是你要想到精益求精 所以这样做不好
其实有O(Nlog N)做法
对于每一种颜色的 影响的是以这个点为端点的一条链 然后对于询问x y可以差分出四条链
我们关键是维护一条链怎么办 发现如果这个点+1了 子树内的肯定也+1
那么就是维护一个树状数组 这个点打一个+1标记 这个子树外的第一个点打一个-1标记 然后用树状数组维护前缀和即可
好像常数还没写O(N2logN)好...
#include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; const int Maxn=500010; struct EDGE{int x,y,next;}edge[Maxn]; int len,first[Maxn]; void ins(int x,int y){len++; edge[len].x=x; edge[len].y=y; edge[len].next=first[x]; first[x]=len;} struct node1 { int t,op,x,c; node1(){} node1(int _t,int _x,int _c,int _op){t=_t; x=_x; c=_c; op=_op;} }Q1[Maxn*4]; int Q1len=0; struct node2 { int t,x,y,c; node2(){} node2(int _t,int _x,int _y,int _c){t=_t; x=_x; y=_y; c=_c;} }Q2[Maxn*4]; int Q2len=0; int L[Maxn],R[Maxn],id=0; int fa[Maxn][21],dep[Maxn]; void Dfs(int x,int f) { L[x]=++id; for(int k=first[x];k!=-1;k=edge[k].next) { int y=edge[k].y; if(y==f) continue; fa[y][0]=x; dep[y]=dep[x]+1; Dfs(y,x); }R[x]=id; } bool Cmp1(const node1 &x,const node1 &y) { if(x.c!=y.c) return x.c<y.c; return x.t<y.t; } bool Cmp2(const node2 &x,const node2 &y) { if(x.c!=y.c) return x.c<y.c; return x.t<y.t; } bool Cmp3(const node2 &x,const node2 &y){return x.t<y.t;} int N,q; int preC[Maxn],C[Maxn],Clen=0; int ans[Maxn]; int tr[Maxn]; int low_bit(int x){return x&(-x);} void Add(int x,int c){while(x<=N){tr[x]+=c; x+=low_bit(x);}} int Query(int x){int ans=0; while(x>=1){ans+=tr[x]; x-=low_bit(x);} return ans;} void Del(int x){while(x<=N){tr[x]=0; x+=low_bit(x);}} int LCA(int x,int y) { if(dep[x]<dep[y]) swap(x,y); int deep=dep[x]-dep[y]; for(int i=20;i>=0;i--) if(deep>=(1<<i)) deep-=(1<<i),x=fa[x][i]; if(x==y) return x; for(int i=20;i>=0;i--) if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i]; return fa[x][0]; } int main() { scanf("%d%d",&N,&q); for(int i=1;i<=N;i++) scanf("%d",&preC[i]),C[++Clen]=preC[i]; for(int i=1;i<=N;i++) Q1[++Q1len]=node1(0,i,preC[i],1); len=0; memset(first,-1,sizeof(first)); for(int i=1;i<N;i++){int x,y; scanf("%d%d",&x,&y); ins(x,y); ins(y,x);} id=0; dep[1]=1; Dfs(1,0); for(int j=1;j<=20;j++) for(int i=1;i<=N;i++) fa[i][j]=fa[fa[i][j-1]][j-1]; for(int i=1;i<=q;i++) { char ch; scanf("\n%c",&ch); if(ch==‘C‘) { int x,c; scanf("%d%d",&x,&c); C[++Clen]=c; if(c!=preC[x]) { Q1[++Q1len]=node1(i,x,preC[x],-1); Q1[++Q1len]=node1(i,x,c,1); preC[x]=c; } } else { int x,y,c; scanf("%d%d%d",&x,&y,&c); Q2[++Q2len]=node2(i,x,y,c); C[++Clen]=c; } } sort(Q1+1,Q1+Q1len+1,Cmp1); sort(Q2+1,Q2+Q2len+1,Cmp2); sort(C+1,C+Clen+1); Clen=unique(C+1,C+Clen+1)-(C+1); int l1=1,l2=1,r1=0,r2=0; for(int i=1;i<=Clen;i++) { int x=C[i]; while(Q1[r1+1].c==C[i] && r1<=Q1len) r1++; while(Q2[r2+1].c==C[i] && r2<=Q2len) r2++; int last=l1; while(l1<=r1 && l2<=r2) { if(Q1[l1].t<Q2[l2].t) { Add(R[Q1[l1].x]+1,(-1)*Q1[l1].op); Add(L[Q1[l1].x],1*Q1[l1].op); l1++; } else { int r=LCA(Q2[l2].x,Q2[l2].y); ans[Q2[l2].t]=Query(L[Q2[l2].x])+Query(L[Q2[l2].y])-Query(L[r])-Query(L[fa[r][0]]); l2++; } } while(l1<=r1) l1++; while(l2<=r2) { int r=LCA(Q2[l2].x,Q2[l2].y); ans[Q2[l2].t]=Query(L[Q2[l2].x])+Query(L[Q2[l2].y])-Query(L[r])-Query(L[fa[r][0]]); l2++; } while(last<=r1) Del(R[Q1[last].x]+1),Del(L[Q1[last].x]),last++; } sort(Q2+1,Q2+Q2len+1,Cmp3); for(int i=1;i<=Q2len;i++) printf("%d\n",ans[Q2[i].t]); return 0; }
时间: 2024-12-28 11:54:56