bzoj 2243(大学ACM恢复训练)

2243: [SDOI2011]染色

Time Limit: 20 Sec  Memory Limit: 512 MB
Submit: 10083  Solved: 3843
[Submit][Status][Discuss]

Description

给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。

 

裸的链剖,写加调55分钟,代码能力太差。不要有畏惧心理,多写来提高。

注意把函数模块化,更新统一写

注意区间合并的先后顺序,深度小的在上,相当于左区间。链顶合并相当于左左合并,要特判。

维护左右端点颜色即可

链剖中链查询可以对每条链建线段树,应该快些,但因为线段树太丑反而更慢。

所以留坑,优化线段树。。。

 

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<algorithm>
  5 using namespace std;
  6 #define maxn 100020
  7 
  8 struct node{
  9     int next,to;
 10 }e[maxn * 2];
 11 struct data{
 12     int lc,rc,num;
 13     data(){ lc = rc = num = 0; }
 14     data(int a,int b,int c):lc(a),rc(b),num(c){};
 15 };
 16 struct node2{
 17     int ls,rs,tag;
 18     data dt;
 19 }sgt[maxn * 20];
 20 int head[maxn],cnt;
 21 int n,m,col[maxn],tot,root[maxn];
 22 int sz[maxn],son[maxn],fa[maxn],id[maxn],top[maxn],dth[maxn],len[maxn];
 23 
 24 inline void adde(int x,int y){
 25     e[++cnt].to = y;
 26     e[cnt].next = head[x];
 27     head[x] = cnt;
 28 }
 29 void dfs(int x){
 30     sz[x] = 1;
 31     for (int i = head[x] ; i ; i = e[i].next){
 32         if ( e[i].to == fa[x] ) continue;
 33         fa[e[i].to] = x , dth[e[i].to] = dth[x] + 1;
 34         dfs(e[i].to);
 35         sz[x] += sz[e[i].to];
 36         if ( sz[son[x]] < sz[e[i].to] ) son[x] = e[i].to; 
 37     }
 38 }
 39 void dfs2(int x){
 40     if ( son[x] ){
 41         top[son[x]] = top[x] , id[son[x]] = ++len[top[x]];
 42         dfs2(son[x]);
 43     }
 44     for (int i = head[x] ; i ; i = e[i].next){
 45         if ( e[i].to == fa[x] || e[i].to == son[x] ) continue;
 46         top[e[i].to] = e[i].to , id[e[i].to] = len[e[i].to] = 1;
 47         dfs2(e[i].to);
 48     }
 49 }
 50 inline data update(data dt1,data dt2){
 51     data cur;
 52     cur.num = dt1.num + dt2.num - (dt1.rc == dt2.lc);
 53     if ( dt1.num && dt2.num ) cur.lc = dt1.lc , cur.rc = dt2.rc;
 54     else if ( dt1.num ) cur.lc = dt1.lc , cur.rc = dt1.rc;
 55     else if ( dt2.num ) cur.lc = dt2.lc , cur.rc = dt2.rc;
 56     return cur;
 57 }
 58 inline void cov(int x,int c){
 59     if ( !x ) return;
 60     sgt[x].dt = data(c,c,1);
 61     sgt[x].tag = c;
 62 }
 63 inline void pushdown(int x){
 64     if ( sgt[x].tag != -1 ){
 65         int ls = sgt[x].ls , rs = sgt[x].rs;
 66         cov(ls,sgt[x].tag) , cov(rs,sgt[x].tag);
 67         sgt[x].tag = -1;
 68     }
 69 }
 70 /*inline void update(int x){
 71     int ls = sgt[x].ls , rs = sgt[x].rs;
 72     sgt[x].num = sgt[ls].num + sgt[rs].num - (sgt[ls].rc == sgt[rs].lc);
 73     if ( ls && rs ) sgt[x].lc = sgt[ls].lc , sgt[x].rc = sgt[rs].rc;
 74     else if ( ls ) sgt[x].lc = sgt[ls].lc , sgt[x].rc = sgt[ls].rc;
 75     else sgt[x].lc = sgt[rs].lc , sgt[x].rc = sgt[rs].rc;
 76 }*/
 77 void insert(int &x,int l,int r,int id,int c){
 78     if ( !x ) x = ++tot , sgt[x].tag = -1;
 79     if ( l == r ){    sgt[x].dt = data(c,c,1); return; }
 80     int mid = (l + r) >> 1;
 81     if ( id <= mid ) insert(sgt[x].ls,l,mid,id,c);
 82     else insert(sgt[x].rs,mid + 1,r,id,c);
 83     sgt[x].dt = update(sgt[sgt[x].ls].dt,sgt[sgt[x].rs].dt);
 84 }
 85 void build(){
 86     for (int i = 1 ; i <= n ; i++)
 87         insert(root[top[i]],1,len[top[i]],id[i],col[i]);
 88 }
 89 void modify(int x,int l,int r,int ls,int rs,int c){
 90     if ( !x ) return;
 91     if ( ls <= l && rs >= r ){ cov(x,c); return; }
 92     pushdown(x);
 93     int mid = (l + r) >> 1;
 94     if ( ls <= mid ) modify(sgt[x].ls,l,mid,ls,rs,c);
 95     if ( rs > mid ) modify(sgt[x].rs,mid + 1,r,ls,rs,c);
 96     sgt[x].dt = update(sgt[sgt[x].ls].dt,sgt[sgt[x].rs].dt);
 97 }
 98 data query(int x,int l,int r,int ls,int rs){
 99     if ( !x ) return data(0,0,0);
100     pushdown(x);
101     if ( ls <= l && rs >= r ) return sgt[x].dt;
102     int mid = (l + r) >> 1; data dt1,dt2;
103     if ( ls <= mid ) dt1 = query(sgt[x].ls,l,mid,ls,rs);
104     if ( rs > mid ) dt2 = query(sgt[x].rs,mid + 1,r,ls,rs);
105     return update(dt1,dt2);
106 }
107 int query(int x,int y){
108     data dt1,dt2,dt3;
109     while ( top[x] != top[y] ){
110         if ( dth[top[x]] > dth[top[y]] ){
111             dt1 = update(query(root[top[x]],1,len[top[x]],1,id[x]),dt1); //左边深度更小,注意合并顺序
112             x = fa[top[x]];
113         }
114         else{
115             dt2 = update(query(root[top[y]],1,len[top[y]],1,id[y]),dt2);
116             y = fa[top[y]];
117         }
118     }
119     //链顶合并有特殊情况
120     if ( dth[x] < dth[y] )
121         dt2 = update(query(root[top[x]],1,len[top[x]],id[x],id[y]),dt2);
122     else
123         dt1 = update(query(root[top[x]],1,len[top[x]],id[y],id[x]),dt1);
124     swap(dt1.lc,dt1.rc);
125     return update(dt1,dt2).num;
126 }
127 void modify(int x,int y,int c){
128     while ( top[x] != top[y] ){
129         if ( dth[top[x]] < dth[top[y]] ) swap(x,y);
130         modify(root[top[x]],1,len[top[x]],1,id[x],c);
131         x = fa[top[x]];
132     }
133     if ( dth[x] < dth[y] ) modify(root[top[x]],1,len[top[x]],id[x],id[y],c);
134     else modify(root[top[x]],1,len[top[x]],id[y],id[x],c);
135 }
136 int main(){
137     freopen("input.txt","r",stdin);
138     scanf("%d %d",&n,&m);
139     for (int i = 1 ; i <= n ; i++) scanf("%d",&col[i]);
140     for (int i = 1 ; i < n ; i++){
141         int x,y;
142         scanf("%d %d",&x,&y);
143         adde(x,y) , adde(y,x);
144     }
145     dfs(1) , id[1] = len[1] = top[1] = 1 , dfs2(1) , build();
146     while ( m-- ){
147         char ch[10]; int a,b,c;
148         scanf("%s",ch);
149         if ( ch[0] == 'Q' ){
150             scanf("%d %d",&a,&b);
151             printf("%d\n",query(a,b));
152         }
153         else{
154             scanf("%d %d %d",&a,&b,&c);
155             modify(a,b,c);
156         }
157     }
158     return 0;
159 }
View Code

 

posted @ 2018-06-29 12:01  zhangqingqi  阅读(124)  评论(0编辑  收藏  举报