BZOJ2243: [SDOI2011]染色
阿新 • • 發佈:2017-09-13
scu 節點數 scrip 區間 eof wap con odi pos
Submit: 8402 Solved: 3151
[Submit][Status][Discuss]
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
1
2
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 8402 Solved: 3151
[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 52 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
31
2
HINT
數N<=10^5,操作數M<=10^5,所有的顏色C為整數且在[0, 10^9]之間。
思路{
顏色段發現用樹鏈剖分的時候記錄一下區間左右端點,比較一下就可以了.
有點碼.....
}
#include<bits/stdc++.h> #define il inline #define RG register #define ll long long #define db double #define N 100010 using namespace std; int w[N]; struct ed{int nxt,to;}e[N*2]; int head[N],tot,n,m; void LINK(int u,int v){e[tot].nxt=head[u];e[tot].to=v;head[u]=tot++;} void link(int u,int v){LINK(u,v),LINK(v,u);} namespace Tree{ #define ls (o<<1) #define rs ((o<<1)|1) #define mid ((l+r)>>1) int id[N],top[N],deep[N],idw[N],fa[N],sz[N],hson[N],idn; int Sum[N*4],lc[N*4],rc[N*4],lazy[N*4]; void dfs1(int u,int faa){ deep[u]=deep[faa]+1;fa[u]=faa;sz[u]=1; for(int i=head[u];i!=-1;i=e[i].nxt)if(e[i].to!=faa){ int v=e[i].to;dfs1(v,u); sz[u]+=sz[v];if(sz[v]>sz[hson[u]])hson[u]=v; } } void dfs2(int u,int toop){ id[u]=++idn;idw[idn]=w[u];top[u]=toop; if(hson[u])dfs2(hson[u],toop); for(int i=head[u];i!=-1;i=e[i].nxt) if(e[i].to!=hson[u]&&e[i].to!=fa[u]) dfs2(e[i].to,e[i].to); } void up(int o){ Sum[o]=Sum[ls]+Sum[rs]; if(rc[ls]==lc[rs])Sum[o]--; rc[o]=rc[rs],lc[o]=lc[ls]; } void build(int o,int l,int r){ if(l==r){Sum[o]=1,rc[o]=lc[o]=idw[l];return;} build(rs,mid+1,r),build(ls,l,mid); up(o); } void down(int o){ if(lazy[o]){ Sum[rs]=Sum[ls]=1; rc[rs]=lc[rs]=lazy[rs]=lazy[o]; rc[ls]=lc[ls]=lazy[ls]=lazy[o]; lazy[o]=0; } } void Modify(int o,int l,int r,int L,int R,int c){ if(l!=r)down(o); if(l>=L&&r<=R){ Sum[o]=1; rc[o]=lc[o]=lazy[o]=c; return; } if(mid<L)Modify(rs,mid+1,r,L,R,c); else if(mid>=R)Modify(ls,l,mid,L,R,c); else Modify(rs,mid+1,r,mid,R,c),Modify(ls,l,mid,L,mid,c); up(o); } int Query(int o,int l,int r,int L,int R){ if(l!=r)down(o); if(l>=L&&r<=R)return Sum[o]; if(mid<L)return Query(rs,mid+1,r,L,R); if(mid>=R)return Query(ls,l,mid,L,R); else return Query(rs,mid+1,r,L,R)+Query(ls,l,mid,L,R)-(rc[ls]==lc[rs]); } int Querycol(int o,int l,int r,int pos){ if(l!=r)down(o);if(l==r)return rc[o]; if(mid<pos)return Querycol(rs,mid+1,r,pos); else return Querycol(ls,l,mid,pos); } void work1(int x,int y,int c){ while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); Modify(1,1,n,id[top[x]],id[x],c); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); Modify(1,1,n,id[x],id[y],c); } void work2(int x,int y){ ll sum(0); while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); sum+=Query(1,1,n,id[top[x]],id[x]); if(Querycol(1,1,n,id[top[x]])==Querycol(1,1,n,id[fa[top[x]]]))sum--; x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); sum+=Query(1,1,n,id[x],id[y]); cout<<sum<<"\n"; } } char C[2]; int main(){ memset(head,-1,sizeof(head)); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i)scanf("%d",&w[i]); for(int i=1;i<n;++i){int u,v;scanf("%d%d",&u,&v),link(u,v);} Tree::dfs1(1,1),Tree::dfs2(1,1);Tree::build(1,1,n); for(int i=1;i<=m;++i){ scanf("%s",C); if(C[0]==‘C‘){ int a,b,c;scanf("%d%d%d",&a,&b,&c); Tree::work1(a,b,c); } else { int a,b;scanf("%d%d",&a,&b); Tree::work2(a,b); } } return 0; }
BZOJ2243: [SDOI2011]染色