BZOJ4999: This Problem Is Too Simple!树链剖分+动态开点线段树
题目大意:将某个节点的颜色变为x,查询i,j路径上多少个颜色为x的点...
其实最开始一看就是主席树+树状数组+DFS序...但是过不去...MLE+TLE BY FCWWW
其实树剖裸的一批...只是在树剖上套一个动态开点的线段树就可以了...很显然的...就是注意一下细节问题,还有Map这种东西,还是不要乱用的说...
附上代码:
#include <cstdio> #include <algorithm> #include <cmath> #include <cstring> #include <cstdlib> #include <queue> #include <iostream> #include <map> using namespace std; #define N 100005 #define lson l,m,tr[rt].ls #define rson m+1,r,tr[rt].rs struct edge{int to,next;}e[N<<1]; struct node{int ls,rs,siz;}tr[N*40]; int rot[N],n,Q,cnt,a[N],head[N],son[N],fa[N],dep[N],siz[N],anc[N],idx[N],tims; void add(int x,int y){e[cnt]=(edge){y,head[x]};head[x]=cnt++;} void Update(int x,int c,int l,int r,int &rt) { if(!rt)rt=++cnt;tr[rt].siz+=c;if(l==r)return ;int m=(l+r)>>1; if(m>=x)Update(x,c,lson);else Update(x,c,rson); } void dfs1(int x,int from) { fa[x]=from,dep[x]=dep[from]+1,siz[x]=1; for(int i=head[x];i!=-1;i=e[i].next) { int to1=e[i].to; if(to1!=from) { dfs1(to1,x);siz[x]+=siz[to1]; if(siz[son[x]]<siz[to1])son[x]=to1; } } } void dfs2(int x,int top) { anc[x]=top;idx[x]=++tims; if(son[x])dfs2(son[x],top); for(int i=head[x],to1;i!=-1;i=e[i].next) { if((to1=e[i].to)!=fa[x]&&to1!=son[x])dfs2(to1,to1); } } int query(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return tr[rt].siz;int m=(l+r)>>1,ret=0; if(L<=m)ret+=query(L,R,lson);if(m<R)ret+=query(L,R,rson);return ret; } int get_lca(int x,int y,int c) { int ret=0; while(anc[x]!=anc[y]) { if(dep[anc[x]]<dep[anc[y]])swap(x,y); ret+=query(idx[anc[x]],idx[x],1,n,rot[c]); x=fa[anc[x]]; }if(dep[x]>dep[y])swap(x,y); return ret+query(idx[x],idx[y],1,n,rot[c]); } map<int ,int>mp;int tot=0,S[N],top,b[N];char s[2]; int main() { scanf("%d%d",&n,&Q);memset(head,-1,sizeof(head)); for(int i=1,x;i<=n;i++) { scanf("%d",&x);b[i]=x; if(mp.find(x)==mp.end())mp[x]=++tot; a[i]=mp[x]; }for(int i=1,x,y;i<n;i++)scanf("%d%d",&x,&y),add(x,y),add(y,x);cnt=0; dfs1(1,0);dfs2(1,1);for(int i=1;i<=n;i++)Update(idx[i],1,1,n,rot[a[i]]); while(Q--) { int x,y,z;scanf("%s%d%d",s,&x,&y); if(s[0]=='C') { Update(idx[x],-1,1,n,rot[a[x]]); if(tr[rot[a[x]]].siz==0)S[++top]=a[x],mp.erase(mp.find(b[x]));b[x]=y; if(mp.find(y)==mp.end()) { if(top)mp[y]=S[top--]; else mp[y]=++tot; }y=mp[y]; Update(idx[x],1,1,n,rot[y]);a[x]=y; }else { scanf("%d",&z); if(mp.find(z)==mp.end()){puts("0");continue;} printf("%d\n",get_lca(x,y,mp[z])); } } }