题解报告——[SDOI2011]染色

Posted genius777

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了题解报告——[SDOI2011]染色相关的知识,希望对你有一定的参考价值。

传送门

 

题目描述

 

技术分享图片

 

输入输出格式

输入格式:

 

 

技术分享图片

 

 

输出格式:

 

 

对于每个询问操作,输出一行答案。

 

 

 

输入输出样例

 

输入样例#1: 复制
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
输出样例#1: 复制
3
1
2

 

说明

 

技术分享图片

 

技术分享图片


 

【思路分析】

看到这道题得第一想法就是树剖,很显然这确实是一道树剖的板题,但是却也是一个练习树剖的很好选择,至少我做完这道题对树剖又有了新的理解,其中也有很多细节需要注意的,考验调试能力。

首先我们用树剖维护树的链,用线段树维护链上权值。这里很好的是维护区间段数,而不是区间上的种类数,所有可以用线段树维护。

【细节注意】

这里我们会发现我们树剖其实是每次要将一条链分开,每一段单独进行查询,所以我们每次查询要比较这一次查询和上一段之间是否有同一段。

由于是树剖,我们每次后查询的区间,在线段树上一定是在前面,所以我们要比较本次查询的右端点和上一次查询的左端点

由于我们是从两个节点向LCA跳,所以我们要记录两个变量,lasta,lastb,分别表示上一次从某个方向跳来的链的端点颜色,然后进行比较即可

【代码实现】

  1 #include<cstdio>
  2 #include<algorithm>
  3 using namespace std;
  4 const int maxn=1e5+5;
  5 struct sd{
  6     int to,next;
  7 }edge[maxn<<1];
  8 struct sd1{
  9     int l,r,son[2],sum,lkind,rkind,lazy;
 10 }t[maxn<<2];
 11 int head[maxn],siz[maxn],top[maxn],mxson[maxn],dep[maxn],fa[maxn],id[maxn],ord[maxn],col[maxn],cnt,lnode,rnode;
 12 void update(int v)
 13 {
 14     int ls=t[v].son[0],rs=t[v].son[1];
 15     t[v].sum=t[ls].sum+t[rs].sum;
 16     if(t[ls].rkind==t[rs].lkind) t[v].sum--;
 17     t[v].lkind=t[ls].lkind,t[v].rkind=t[rs].rkind;
 18 }
 19 void pushdown(int v)
 20 {
 21     if(t[v].lazy)
 22     {
 23         int ls=t[v].son[0],rs=t[v].son[1];
 24         if(ls) t[ls].sum=1,t[ls].lazy=t[ls].lkind=t[ls].rkind=t[v].lazy;
 25         if(rs) t[rs].sum=1,t[rs].lazy=t[rs].lkind=t[rs].rkind=t[v].lazy;
 26         t[v].lazy=0;
 27     }
 28 }
 29 void build(int &v,int l,int r)
 30 {
 31     v=++cnt;t[v].l=l,t[v].r=r;
 32     if(l==r) {t[v].lkind=t[v].rkind=col[ord[l]],t[v].sum=1;return;}
 33     int mid=(l+r)>>1;
 34     build(t[v].son[0],l,mid);
 35     build(t[v].son[1],mid+1,r);
 36     update(v);
 37 }
 38 void add_edge(int from,int to)
 39 {
 40     edge[++cnt].to=to;
 41     edge[cnt].next=head[from];
 42     head[from]=cnt;
 43 }
 44 void dfs(int v,int ff,int deep)
 45 {
 46     fa[v]=ff,dep[v]=deep,siz[v]=1;
 47     int MS=0,MX=0;
 48     for(int i=head[v];i;i=edge[i].next)
 49     {
 50         int to=edge[i].to;
 51         if(to!=ff)
 52         {
 53             dfs(to,v,deep+1);
 54             if(MX<siz[to]) MX=siz[to],MS=to;
 55             siz[v]+=siz[to];
 56         }
 57     }
 58     mxson[v]=MS;
 59 }
 60 void dfs2(int v,int tt)
 61 {
 62     top[v]=tt,ord[++cnt]=v,id[v]=cnt;
 63     if(!mxson[v]) return;
 64     dfs2(mxson[v],tt);
 65     for(int i=head[v];i;i=edge[i].next)
 66     {
 67         if(edge[i].to!=fa[v]&&edge[i].to!=mxson[v])
 68             dfs2(edge[i].to,edge[i].to);
 69     }
 70 }
 71 void change(int v,int l,int r,int kk)
 72 {
 73     if(t[v].l==l&&t[v].r==r)
 74     {
 75         t[v].sum=1,t[v].lkind=t[v].rkind=t[v].lazy=kk;
 76         return;
 77     }
 78     pushdown(v);
 79     int mid=(t[v].l+t[v].r)>>1,ls=t[v].son[0],rs=t[v].son[1];
 80     if(r<=mid) change(ls,l,r,kk);
 81     else if(l>mid) change(rs,l,r,kk);
 82     else change(ls,l,mid,kk),change(rs,mid+1,r,kk);
 83     update(v);
 84 }
 85 int ask(int v,int l,int r,int ql,int qr)
 86 {
 87     pushdown(v);
 88     if(t[v].l==l&&t[v].r==r)
 89     {
 90         if(t[v].l==ql) lnode=t[v].lkind;
 91         if(t[v].r==qr) rnode=t[v].rkind;
 92         return t[v].sum;
 93     }
 94     int mid=(t[v].l+t[v].r)>>1,ls=t[v].son[0],rs=t[v].son[1];
 95     if(r<=mid) return ask(ls,l,r,ql,qr);
 96     else if(l>mid) return ask(rs,l,r,ql,qr);
 97     else 
 98     {
 99         int ans=0;
100         ans+=ask(ls,l,mid,ql,qr);
101         ans+=ask(rs,mid+1,r,ql,qr);
102         if(t[ls].rkind==t[rs].lkind) ans--;
103         return ans;
104     }
105 }
106 void LCA_change(int a,int b,int kk)
107 {
108     while(top[a]!=top[b])
109     {
110         if(dep[top[a]]<dep[top[b]]) swap(a,b);
111         change(1,id[top[a]],id[a],kk);
112         a=fa[top[a]];
113     }
114     if(dep[b]<dep[a]) swap(a,b);
115     change(1,id[a],id[b],kk);
116 }
117 int LCA_ask(int a,int b)
118 {
119     int ans=0,lasta=-1,lastb=-1;
120     while(top[a]!=top[b])
121     {
122         if(dep[top[a]]>dep[top[b]])
123         {
124             ans+=ask(1,id[top[a]],id[a],id[top[a]],id[a]);
125             if(rnode==lasta&&lasta!=-1) ans--;
126             lasta=lnode;
127             a=fa[top[a]];
128         }
129         else
130         {
131             ans+=ask(1,id[top[b]],id[b],id[top[b]],id[b]);
132             if(rnode==lastb&&lastb!=-1) ans--;
133             lastb=lnode;
134             b=fa[top[b]];
135         }
136     }
137     if(dep[a]<dep[b])
138     {
139         ans+=ask(1,id[a],id[b],id[a],id[b]);
140         if(lasta==lnode) ans--;
141         if(lastb==rnode) ans--;
142      }
143     else
144     {
145         ans+=ask(1,id[b],id[a],id[b],id[a]);
146         if(lasta==rnode) ans--;
147         if(lastb==lnode) ans--;
148     }
149     return ans;
150 }
151 int main()
152 {
153     int n,m,a,b,c,rt;
154     scanf("%d%d",&n,&m);
155     for(int i=1;i<=n;i++) scanf("%d",&col[i]);
156     for(int i=1;i<n;i++) scanf("%d%d",&a,&b),add_edge(a,b),add_edge(b,a);
157     cnt=0,dfs(1,0,1),dfs2(1,1);
158     cnt=0,build(rt,1,n);
159     while(m--)
160     {
161         char ch[3];
162         scanf("%s%d%d",ch,&a,&b);
163         if(ch[0]==Q) printf("%d
",LCA_ask(a,b));
164         else scanf("%d",&c),LCA_change(a,b,c);
165     }
166     return 0;
167 }

 

以上是关于题解报告——[SDOI2011]染色的主要内容,如果未能解决你的问题,请参考以下文章

luogu题解P2486[SDOI2011]染色--树链剖分+trick

[Luogu 2486] SDOI2011 染色

[SDOI2011]染色

P2486 [SDOI2011]染色

洛谷 P2486 [SDOI2011]染色

[BZOJ]2243: [SDOI2011]染色