bzoj 2243(大学ACM恢复训练)
2243: [SDOI2011]染色
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 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 }