【bzoj2243】[SDOI2011]染色
2017-03-19 10:17
369 查看
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
Sample Output
3
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解
树链剖分,线段树记录区间颜色段数,与左右两端颜色,这样就可以合并计算了。注意答案的统计。
代码
给定一棵有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
Sample Output
3
1
2
HINT
数N<=10^5,操作数M<=10^5,所有的颜色C为整数且在[0, 10^9]之间。
题解
树链剖分,线段树记录区间颜色段数,与左右两端颜色,这样就可以合并计算了。注意答案的统计。
代码
#include<cstdio> #include<iostream> #include<cstring> #include<cmath> int n,m,tim,tot; struct seg{int l;int r;int n;}t[400005]; int Head[100005],ret[200005],Next[200005],bl[100005]; int son[100005],size[100005],pos[100005],c[100005]; int fa[100005],dep[100005],lazy[400005]; using namespace std; int read(){ int x=0,f=1; char ch; ch=getchar(); while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();} while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } void ins(int u,int v){ tot++;ret[tot]=v;Next[tot]=Head[u];Head[u]=tot; } void init(){ n=read();m=read(); for (int i=1;i<=n;i++){ c[i]=read(); } for (int i=1;i<n;i++){ int x=read(),y=read(); ins(x,y);ins(y,x); } } void dfs1(int u){ size[u]=1; for (int i=Head[u];i!=0;i=Next[i]){ int v=ret[i]; if (v!=fa[u]){ fa[v]=u; dep[v]=dep[u]+1; dfs1(v); size[u]+=size[v]; if (son[u]==0||size[son[u]]<size[v]){ son[u]=v; } } } } void dfs2(int u,int chain){ tim++; pos[u]=tim; bl[u]=chain; if (son[u]!=0){ dfs2(son[u],chain); } for (int i=Head[u];i!=0;i=Next[i]){ int v=ret[i]; if (v!=fa[u]&&v!=son[u]){ dfs2(v,v); } } } void pushdown(int k,int l,int r){ if (l==r) return; int c=lazy[k];lazy[k]=-1; t[k<<1].n=1;t[k<<1].l=c;t[k<<1].r=c; t[k<<1|1].n=1;t[k<<1|1].l=c;t[k<<1|1].r=c; lazy[k<<1]=c;lazy[k<<1|1]=c; } void change(int k,int l,int r,int x,int y,int color){ if (lazy[k]!=-1) pushdown(k,l,r); if (l==x&&r==y){ t[k].l=color; t[k].r=color; t[k].n=1; lazy[k]=color; return; } int mid=(l+r)/2; if (y<=mid) change(k<<1,l,mid,x,y,color); if (x>mid) change(k<<1|1,mid+1,r,x,y,color); if (x<=mid&&y>mid){ change(k<<1,l,mid,x,mid,color); change(k<<1|1,mid+1,r,mid+1,y,color); } t[k].n=t[k<<1].n+t[k<<1|1].n; t[k].l=t[k<<1].l;t[k].r=t[k<<1|1].r; if (t[k<<1].r==t[k<<1|1].l) t[k].n--; } seg query(int k,int l,int r,int x,int y){ if (lazy[k]!=-1) pushdown(k,l,r); if (l==x&&r==y){ return t[k]; } int mid=(l+r)/2; if (y<=mid) return query(k<<1,l,mid,x,y); if (x>mid) return query(k<<1|1,mid+1,r,x,y); seg a,b,c; a=query(k<<1,l,mid,x,mid); b=query(k<<1|1,mid+1,r,mid+1,y); c.n=a.n+b.n; if (a.r==b.l) c.n--; c.l=a.l;c.r=b.r; return c; } void solvechange(int a,int b,int c){ while (bl[a]!=bl[b]){ if (dep[bl[a]]<dep[bl[b]]) swap(a,b); change(1,1,n,pos[bl[a]],pos[a],c); a=fa[bl[a]]; } if (pos[a]>pos[b]) swap(a,b); change(1,1,n,pos[a],pos[b],c); } int solveask(int x,int y){ int ans=0; seg a,b,c; a.l=-1;a.r=-1;b.l=-1;b.r=-1; while (bl[x]!=bl[y]){ if (dep[bl[x]]<dep[bl[y]]){ swap(x,y); swap(a,b); } c=query(1,1,n,pos[bl[x]],pos[x]); ans+=c.n; if (c.r==a.l) ans--; a=c; x=fa[bl[x]]; } if (pos[x]>pos[y]){ swap(x,y); swap(a,b); } c=query(1,1,n,pos[x],pos[y]); ans+=c.n; if (c.l==a.l) ans--; if (c.r==b.l) ans--; return ans; } void solve(){ for (int i=1;i<=n;i++){ change(1,1,n,pos[i],pos[i],c[i]); } for (int i=1;i<=m;i++){ char ch[10]; scanf("%s",ch); if (ch[0]=='C'){ int a=read(),b=read(),c=read(); solvechange(a,b,c); }else{ int a=read(),b=read(); printf("%d\n",solveask(a,b)); } } } int main(){ memset(lazy,-1,sizeof(lazy)); init(); dfs1(1); dfs2(1,1); solve(); }
相关文章推荐
- _bzoj2243 [SDOI2011]染色【树链剖分】
- bzoj 2243: [SDOI2011]染色
- bzoj2243: [SDOI2011]染色 树链剖分
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
- BZOJ 2243 SDOI 2011 染色 树链剖分
- [BZOJ2243][SDOI2011]染色
- 【BZOJ】2243 [SDOI2011]染色 树链剖分
- [BZOJ2243][SDOI2011]染色
- BZOJ 2243: [SDOI2011]染色 树链剖分
- bzoj2243 [SDOI2011]染色
- BZOJ2243 [SDOI2011]染色
- 【BZOJ2243】[SDOI2011]染色 树链剖分
- BZOJ.2243.[SDOI2011]染色(树链剖分)
- Bzoj-2243 [SDOI2011]染色(动态树/树链剖分)
- bzoj 2243: [SDOI2011]染色
- 【BZOJ2243】【SDOI2011】染色(树链剖分+线段树)
- [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】
- BZOJ 2243: [SDOI2011]染色(树链剖分)
- BZOJ2243 [SDOI2011]染色
- bzoj2243[SDOI2011]染色 (树剖)