题面
强行把序列问题通过树剖套在树上。。。算了算是回顾了一下树剖的思想=。=
每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点都要考虑
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=100005; 6 struct a 7 { 8 int cnt; 9 int lc,rc; 10 }; 11 int num[N],nmb[N],val[4*N],lcol[4*N],rcol[4*N],laz[4*N]; 12 int siz[N],dep[N],anc[N],imp[N],top[N],dfn[N]; 13 int p[N],noww[2*N],goal[2*N]; 14 int n,m,t1,t2,t3,cnt,tot; 15 char rd[2]; 16 void link(int f,int t) 17 { 18 noww[++cnt]=p[f]; 19 goal[cnt]=t,p[f]=cnt; 20 } 21 void DFS(int nde,int fth,int dth) 22 { 23 int tmp=0; 24 siz[nde]=1,anc[nde]=fth,dep[nde]=dth; 25 for(int i=p[nde];i;i=noww[i]) 26 if(goal[i]!=fth) 27 { 28 DFS(goal[i],nde,dth+1); 29 siz[nde]+=siz[goal[i]]; 30 if(siz[goal[i]]>tmp) 31 tmp=siz[goal[i]],imp[nde]=goal[i]; 32 } 33 } 34 void MARK(int nde,int tpp) 35 { 36 dfn[nde]=++tot,nmb[tot]=num[nde],top[nde]=tpp; 37 if(imp[nde]) 38 { 39 MARK(imp[nde],tpp); 40 for(int i=p[nde];i;i=noww[i]) 41 if(goal[i]!=anc[nde]&&goal[i]!=imp[nde]) 42 MARK(goal[i],goal[i]); 43 } 44 } 45 void pushup(int nde) 46 { 47 int ls=2*nde,rs=2*nde+1; 48 lcol[nde]=lcol[ls],rcol[nde]=rcol[rs]; 49 val[nde]=val[ls]+val[rs]-(rcol[ls]==lcol[rs]); 50 } 51 void create(int nde,int l,int r) 52 { 53 if(l==r) 54 val[nde]=1,lcol[nde]=rcol[nde]=nmb[l]; 55 else 56 { 57 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; 58 create(ls,l,mid),create(rs,mid+1,r); 59 pushup(nde); 60 } 61 } 62 void release(int nde,int l,int r) 63 { 64 if(laz[nde]) 65 { 66 int ls=2*nde,rs=2*nde+1; 67 laz[ls]=lcol[ls]=rcol[ls]=laz[nde]; 68 laz[rs]=lcol[rs]=rcol[rs]=laz[nde]; 69 val[ls]=val[rs]=1; laz[nde]=0; 70 } 71 } 72 void change(int nde,int l,int r,int nl,int nr,int task) 73 { 74 if(l>nr||r<nl) 75 return ; 76 else if(l>=nl&&r<=nr) 77 val[nde]=1,lcol[nde]=rcol[nde]=laz[nde]=task; 78 else 79 { 80 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r); 81 change(ls,l,mid,nl,nr,task),change(rs,mid+1,r,nl,nr,task); 82 pushup(nde); 83 } 84 } 85 a query(int nde,int l,int r,int nl,int nr) 86 { 87 if(l>=nl&&r<=nr) 88 return (a){val[nde],lcol[nde],rcol[nde]}; 89 else 90 { 91 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; release(nde,l,r); 92 if(nr<=mid) return query(ls,l,mid,nl,nr); 93 if(nl>mid) return query(rs,mid+1,r,nl,nr); 94 a r1=query(ls,l,mid,nl,nr),r2=query(rs,mid+1,r,nl,nr),ret; 95 ret.lc=r1.lc,ret.rc=r2.rc,ret.cnt=r1.cnt+r2.cnt-(r1.rc==r2.lc); 96 return ret; 97 } 98 } 99 void path_change(int x,int y,int v) 100 { 101 while(top[x]!=top[y]) 102 { 103 if(dep[top[x]]<dep[top[y]]) swap(x,y); 104 change(1,1,n,dfn[top[x]],dfn[x],v); x=anc[top[x]]; 105 } 106 if(dep[x]>dep[y]) swap(x,y); 107 change(1,1,n,dfn[x],dfn[y],v); return ; 108 } 109 int path_query(int x,int y) 110 { 111 int rt=0,ll=-1,rr=-1; 112 while(top[x]!=top[y]) 113 { 114 if(dep[top[x]]<dep[top[y]]) swap(x,y),swap(ll,rr); 115 a ret=query(1,1,n,dfn[top[x]],dfn[x]); x=anc[top[x]]; 116 rt+=ret.cnt-(ll==ret.rc); ll=ret.lc; 117 } 118 if(dep[x]>dep[y]) swap(x,y),swap(ll,rr); 119 a ret=query(1,1,n,dfn[x],dfn[y]); rt+=ret.cnt-(ll==ret.lc)-(rr==ret.rc); 120 return rt; 121 } 122 int main () 123 { 124 scanf("%d%d",&n,&m); 125 for(int i=1;i<=n;i++) 126 scanf("%d",&num[i]); 127 for(int i=1;i<n;i++) 128 scanf("%d%d",&t1,&t2),link(t1,t2),link(t2,t1); 129 DFS(1,0,1); MARK(1,1); create(1,1,n); 130 while(m--) 131 { 132 scanf("%s",rd); 133 if(rd[0]=='C') 134 scanf("%d%d%d",&t1,&t2,&t3),path_change(t1,t2,t3); 135 else 136 scanf("%d%d",&t1,&t2),printf("%d\n",path_query(t1,t2)); 137 } 138 return 0; 139 }