给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作=。
题解:树链剖分+线段树,线段树维护区间左右的颜色和种类数,合并就很简单了,考虑左区间的右端点和右区间的左端点是不是一样颜色,然后树上暴跳的时候要比较深度来跳了,然后修改也是在树上暴跳即可
View Code
/************************************************************** Problem: 2243 User: walfy Language: C++ Result: Accepted Time:5192 ms Memory:48268 kb ****************************************************************/ //#pragma comment(linker, "/stack:200000000") //#pragma GCC optimize("Ofast,no-stack-protector") //#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native") //#pragma GCC optimize("unroll-loops") #include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pi acos(-1.0) #define ll long long #define vi vector<int> #define mod 1000000007 #define C 0.5772156649 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 #define pil pair<int,ll> #define pli pair<ll,int> #define pii pair<int,int> #define cd complex<double> #define ull unsigned long long #define base 1000000000000000000 #define fio ios::sync_with_stdio(false);cin.tie(0) using namespace std; const double g=10.0,eps=1e-12; const int N=400000+10,maxn=400000+10,inf=0x3f3f3f3f,INF=0x3f3f3f3f3f3f3f3f; struct edge{ int to,Next; }e[maxn]; int cnt,head[N]; int son[N],fa[N],top[N],sz[N],id[N]; int res,w[N],re[N],dep[N]; void add(int u,int v) { e[cnt].to=v; e[cnt].Next=head[u]; head[u]=cnt++; } void init() { cnt=0; memset(head,-1,sizeof head); memset(son,-1,sizeof son); } void dfs1(int u,int f,int de) { fa[u]=f;sz[u]=1; dep[u]=de; for(int i=head[u];~i;i=e[i].Next) { int v=e[i].to; if(v!=f) { dfs1(v,u,de+1); sz[u]+=sz[v]; if(son[u]==-1||sz[v]>sz[son[u]])son[u]=v; } } } void dfs2(int u,int f,int tp) { top[u]=tp; id[u]=++res; if(son[u]!=-1)dfs2(son[u],u,tp); for(int i=head[u];~i;i=e[i].Next) { int v=e[i].to; if(v!=f&&v!=son[u])dfs2(v,u,v); } } struct node{ int cl,cr,co; }sum[N<<2]; node gao(node a,node b) { if(a.cl==-1)a=b; else if(b.cl==-1); else { a.co+=b.co; if(a.cr==b.cl)a.co--; a.cr=b.cr; } return a; } int lazy[N<<2]; void pushdown(int rt) { if(lazy[rt]!=-1) { sum[rt<<1].co=sum[rt<<1|1].co=1; sum[rt<<1].cl=sum[rt<<1|1].cl=lazy[rt]; sum[rt<<1].cr=sum[rt<<1|1].cr=lazy[rt]; lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt]; lazy[rt]=-1; } } void pushup(int rt) { sum[rt]=gao(sum[rt<<1],sum[rt<<1|1]); } void build(int l,int r,int rt) { lazy[rt]=-1; if(l==r){sum[rt].cl=sum[rt].cr=w[re[l]];sum[rt].co=1;return ;} int m=(l+r)>>1; build(ls);build(rs); pushup(rt); } void update(int L,int R,int c,int l,int r,int rt) { if(L<=l&&r<=R) { sum[rt].co=1,sum[rt].cl=sum[rt].cr=c; lazy[rt]=c; return ; } pushdown(rt); int m=(l+r)>>1; if(L<=m)update(L,R,c,ls); if(m<R)update(L,R,c,rs); pushup(rt); } node query1(int L,int R,int l,int r,int rt) { if(L<=l&&r<=R)return sum[rt]; pushdown(rt); int m=(l+r)>>1; node ans{-1,-1,0}; if(L<=m)ans=gao(ans,query1(L,R,ls)); if(m<R)ans=gao(ans,query1(L,R,rs)); return ans; } int query(int a,int b) { int f1=top[a],f2=top[b],ans=0; node aa{-1,-1,0},bb{-1,-1,0}; while(f1!=f2) { if(dep[f1]>dep[f2]) { node te=query1(id[f1],id[a],1,res,1); swap(te.cl,te.cr); aa=gao(aa,te); a=fa[f1];f1=top[a]; } else { node te=query1(id[f2],id[b],1,res,1); swap(te.cl,te.cr); bb=gao(bb,te); b=fa[f2];f2=top[b]; } } if(dep[a]<dep[b]) { node te=query1(id[a],id[b],1,res,1); aa=gao(aa,te); swap(bb.cl,bb.cr); aa=gao(aa,bb); } else { node te=query1(id[b],id[a],1,res,1); swap(te.cl,te.cr); aa=gao(aa,te); swap(bb.cl,bb.cr); aa=gao(aa,bb); } return aa.co; } void change(int a,int b,int c) { int f1=top[a],f2=top[b]; while(f1!=f2) { if(dep[f1]<dep[f2])swap(f1,f2),swap(a,b); update(id[f1],id[a],c,1,res,1); a=fa[f1],f1=top[a]; } if(dep[a]>dep[b])swap(a,b); // printf("%d %d %d %d ",id[a],id[b],a,b); update(id[a],id[b],c,1,res,1); } int main() { int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&w[i]); init(); for(int i=1;i<n;i++) { int a,b;scanf("%d%d",&a,&b); add(a,b);add(b,a); } dfs1(1,-1,1); dfs2(1,-1,1); for(int i=1;i<=res;i++)re[id[i]]=i; build(1,res,1); while(m--) { char op[10]; scanf("%s",op); if(op[0]=='C') { int a,b,c;scanf("%d%d%d",&a,&b,&c); change(a,b,c); } else { int a,b;scanf("%d%d",&a,&b); printf("%d ",query(a,b)); } } return 0; } /*********************** 8 100 3 2 2 2 4 1 1 3 1 3 1 5 1 7 3 6 3 4 5 2 2 8 ***********************/