链剖就可以了。一开始的想法错了。但也非常接近了。妈呀调的要死。。。然后把字体再缩小一号查错起来比较容易QAQ。
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; #define rep(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #define clr(x,c) memset(x,c,sizeof(x)) #define qwq(x) for(edge *o=head[x];o;o=o->next) #define lson l,mid,x<<1 #define rson mid+1,r,x<<1|1 int read(){ int x=0;char c=getchar(); while(!isdigit(c)) c=getchar(); while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x; } const int nmax=1e5+5; const int inf=0x7f7f7f7f; struct edge{ int to;edge *next; }; edge es[nmax<<1],*pt=es,*head[nmax]; void add(int u,int v){ pt->to=v;pt->next=head[u];head[u]=pt++; pt->to=u;pt->next=head[v];head[v]=pt++; } int n,m,fa[nmax],son[nmax],dep[nmax],size[nmax],tp[nmax],id[nmax],idx[nmax],w[nmax]; void dfs(int x){ size[x]=1; qwq(x) if(o->to!=fa[x]){ int to=o->to;dep[to]=dep[x]+1,fa[to]=x; dfs(o->to);size[x]+=size[to]; if(!son[x]||size[son[x]]<size[to]) son[x]=to; } } void DFS(int x,int top){ tp[x]=top;id[++id[0]]=x;idx[x]=id[0]; if(son[x]) DFS(son[x],top); qwq(x) if(!idx[o->to]) DFS(o->to,o->to); } int lc[nmax<<2],rc[nmax<<2],sum[nmax<<2],col[nmax<<2]; void pushup(int x){ lc[x]=lc[x<<1];rc[x]=rc[x<<1|1]; sum[x]=sum[x<<1]+sum[x<<1|1]-(rc[x<<1]==lc[x<<1|1]); } void build(int l,int r,int x){ col[x]=-1; if(l==r){ lc[x]=rc[x]=w[id[l]];sum[x]=1;return ; } int mid=(l+r)>>1;build(lson);build(rson);pushup(x); } void print(int l,int r,int x){ printf("%d->%d:%d %d %d %d ",l,r,col[x],lc[x],rc[x],sum[x]); if(l==r) return ; int mid=(l+r)>>1;print(lson);print(rson); } void pushdown(int x){ if(col[x]!=-1){ col[x<<1]=col[x<<1|1]=col[x]; lc[x<<1]=rc[x<<1]=lc[x<<1|1]=rc[x<<1|1]=col[x]; sum[x<<1]=sum[x<<1|1]=1;col[x]=-1; return ; } } void update(int tl,int tr,int p,int l,int r,int x){ if(tl<=l&&tr>=r){ col[x]=p;lc[x]=rc[x]=p;sum[x]=1;return ; } int mid=(l+r)>>1;pushdown(x); if(tl<=mid) update(tl,tr,p,lson); if(tr>mid) update(tl,tr,p,rson); pushup(x); } void UPDATE(int a,int b,int p){ while(tp[a]!=tp[b]){ if(dep[tp[a]]>dep[tp[b]]) swap(a,b); update(idx[tp[b]],idx[b],p,1,n,1); b=fa[tp[b]]; } if(dep[a]>dep[b]) swap(a,b); update(idx[a],idx[b],p,1,n,1); } int query(int tl,int tr,int l,int r,int x){ if(tl<=l&&tr>=r) return sum[x]; int mid=(l+r)>>1;pushdown(x); if(tr<=mid) return query(tl,tr,lson); if(tl>mid) return query(tl,tr,rson); return query(tl,tr,lson)+query(tl,tr,rson)-(rc[x<<1]==lc[x<<1|1]); } int get(int p,int l,int r,int x){ //printf("%d %d %d ",l,r,lc[x]); if(l==r) return lc[x]; int mid=(l+r)>>1;pushdown(x); return p<=mid?get(p,lson):get(p,rson); } void QUERY(int a,int b){ int ans=0; while(tp[a]!=tp[b]){ if(dep[tp[a]]>dep[tp[b]]) swap(a,b); ans+=query(idx[tp[b]],idx[b],1,n,1); //printf("%d %d %d %d %d ",ans,idx[fa[tp[b]]],get(idx[fa[tp[b]]],1,n,1),idx[tp[b]],get(idx[tp[b]],1,n,1)); if(get(idx[fa[tp[b]]],1,n,1)==get(idx[tp[b]],1,n,1)) ans--; b=fa[tp[b]]; } if(dep[a]>dep[b]) swap(a,b); ans+=query(idx[a],idx[b],1,n,1); printf("%d ",ans); } int main(){ n=read(),m=read(); rep(i,1,n) w[i]=read(); int u,v,d; rep(i,1,n-1) u=read(),v=read(),add(u,v); clr(son,0);clr(idx,0);dep[1]=0;id[0]=0; dfs(1);DFS(1,1); //rep(i,1,n) printf("%d %d %d %d %d %d ",fa[i],son[i],dep[i],size[i],tp[i],id[i]); //rep(i,1,n) printf("%d ",id[i]);printf(" "); build(1,n,1); //print(1,n,1); //get(2,1,n,1); char s[5]; rep(i,1,m){ scanf("%s",s);u=read(),v=read(); if(s[0]=='C') d=read(),UPDATE(u,v,d); else QUERY(u,v); } return 0; }
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5972 Solved: 2185
[Submit][Status][Discuss]
Description
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。
Sample Input
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
3
1
2
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。