给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
标签:
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
第一行包含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)路径上的颜色段数量。
对于每个询问操作,输出一行答案。
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
#include<cstdio> #include<cctype> #include<queue> #include<cmath> #include<cstring> #include<algorithm> #define lc ch[x][0] #define rc ch[x][1] #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 ren for(int i=first[x];i;i=next[i]) using namespace std; const int BufferSize=1<<16; char buffer[BufferSize],*head,*tail; inline char Getchar() { if(head==tail) { int l=fread(buffer,1,BufferSize,stdin); tail=(head=buffer)+l; } return *head++; } inline int read() { int x=0,f=1;char c=getchar(); for(;!isdigit(c);c=getchar()) if(c==‘-‘) f=-1; for(;isdigit(c);c=getchar()) x=x*10+c-‘0‘; return x*f; } const int maxn=100010; int ch[maxn][2],fa[maxn],pre[maxn],setv[maxn],val[maxn]; int sumv[maxn],left[maxn],right[maxn]; int s[maxn]; void maintain(int x) { if(!x) return; if(setv[x]) { left[x]=right[x]=setv[x];sumv[x]=1; return; } sumv[x]=sumv[lc]+sumv[rc]+1; if(val[x]==left[rc]) sumv[x]--; if(val[x]==right[lc]) sumv[x]--; left[x]=left[lc]?left[lc]:val[x]; right[x]=right[rc]?right[rc]:val[x]; } void set(int x,int v) { if(!x) return; setv[x]=val[x]=left[x]=right[x]=v;sumv[x]=1; } void pushdown(int x) { if(!x) return; if(setv[x]) { set(lc,setv[x]);set(rc,setv[x]); setv[x]=0; } } void rotate(int x) { int y=pre[x],z=pre[y],d=ch[y][0]==x; ch[y][d^1]=ch[x][d];pre[ch[x][d]]=y; ch[z][ch[z][1]==y]=x;pre[x]=z; ch[x][d]=y;pre[y]=x;maintain(y); } int S[maxn],top; void splay(int x) { for(int i=x;i;i=pre[i]) S[++top]=i; if(top!=1) fa[x]=fa[S[top]],fa[S[top]]=0; while(top) pushdown(S[top--]); while(pre[x]) rotate(x); maintain(x); } void access(int x) { for(int y=0;x;x=fa[x]) { splay(x);pre[ch[x][1]]=0;fa[ch[x][1]]=x; ch[x][1]=y;pre[y]=x;maintain(y=x); } } void solve(int x,int y,int t,int v) { access(y); for(y=0;x;x=fa[x]) { splay(x); if(!fa[x]) { if(t) set(y,v),set(rc,v),val[x]=v,maintain(x); else { int ans=sumv[rc]+sumv[y]+1; if(val[x]==left[rc]) ans--; if(val[x]==left[y]) ans--; printf("%d\n",ans); } return; } pre[ch[x][1]]=0;fa[ch[x][1]]=x; ch[x][1]=y;pre[y]=x;maintain(y=x); } } int first[maxn],next[maxn<<1],to[maxn<<1],e; void AddEdge(int u,int v) { to[++e]=v;next[e]=first[u];first[u]=e; to[++e]=u;next[e]=first[v];first[v]=e; } int Q[maxn],vis[maxn]; void bfs(int x) { int l=1,r=0;Q[++r]=x;vis[x]=1; while(l<=r) { x=Q[l++]; ren if(!vis[to[i]]) { fa[to[i]]=x; Q[++r]=to[i]; vis[to[i]]=1; } } } int main() { int n=read(),m=read(); rep(i,1,n) set(i,read()+1); rep(i,2,n) AddEdge(read(),read()); bfs(1); while(m--) { char c=getchar();while(!isalpha(c)) c=getchar(); int u=read(),v=read(),x,t=0; if(c==‘C‘) x=read()+1,t=1; solve(u,v,t,x); } return 0; }
标签:
原文地址:http://www.cnblogs.com/wzj-is-a-juruo/p/5027376.html