BZOJ2243 [SDOI2011] 染色

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243

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,表示xy之间有一条无向边。

下面 行每行描述一个操作:

“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;

“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。

Output

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

 

显然是树链剖分。把QQ签名改成了“Runtime Error”,结果真灵验换来了10次Runtime Error……

不管怎样还是艰难的AC了,写了一个中午多一点点,调了一节晚自习,一个中午和一个下午放学……找出了n多bug,最严重的是把一个w<<1|1打成了w<<1,这个造成了RE

Segment Tree的每个节点保存:这个节点所代表的区间的左端点颜色、右端点颜色、颜色段数。

合并时如果左区间的右端点颜色等于右区间的左端点颜色就把颜色数量减1

然后查询时如果一条轻链的两个端点颜色相同也要把结果减1

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <algorithm>
  4 #include <cstring>
  5 #define rep(i,l,r) for(int i=l; i<=r; i++)
  6 #define clr(x,y) memset(x,y,sizeof(x))
  7 #define travel(x) for(Edge *p=last[x]; p; p=p->pre)
  8 using namespace std;
  9 const int maxn = 100010;
 10 struct Edge{
 11     Edge *pre;
 12     int to;
 13 }edge[maxn<<1];
 14 Edge *last[maxn],*pt;
 15 struct node{
 16     int l,r,c,s,lc,rc;
 17 }t[maxn<<2];
 18 int n,m,x,y,z,segnum=0,c[maxn],depth[maxn],fa[maxn],pos[maxn],size[maxn],belong[maxn];
 19 char op[10];
 20 bool vis[maxn];
 21 inline int read(){
 22     int ans = 0, f = 1;
 23     char c = getchar();
 24     while (!isdigit(c)){
 25         if (c == '-') f = -1;
 26         c = getchar();
 27     }
 28     while (isdigit(c)){
 29         ans = ans * 10 + c - '0';
 30         c = getchar();
 31     }
 32     return ans * f;
 33 }
 34 inline void addedge(int x,int y){
 35     pt->pre = last[x];
 36     pt->to = y;
 37     last[x] = pt++;
 38 }
 39 void dfs1(int x){
 40     vis[x] = 1; size[x] = 1;
 41     travel(x){
 42         if (vis[p->to]) continue;
 43         depth[p->to] = depth[x] + 1;
 44         fa[p->to] = x;
 45         dfs1(p->to);
 46         size[x] += size[p->to];
 47     }
 48 }
 49 void dfs2(int x,int chain){
 50     int k = 0; pos[x] = ++segnum; belong[x] = chain;
 51     travel(x){
 52         if (depth[p->to] > depth[x] && size[p->to] > size[k])
 53         k = p->to;
 54     }
 55     if (!k) return;
 56     dfs2(k,chain);
 57     travel(x){
 58         if (depth[p->to] > depth[x] && p->to != k) dfs2(p->to,p->to);
 59     }
 60 }
 61 inline void pushdown(int w){
 62     if (t[w].c == -1 || t[w].l == t[w].r) return;
 63     t[w<<1].s = t[w<<1|1].s = 1;
 64     t[w<<1].c = t[w<<1|1].c = t[w].c;
 65     t[w<<1].lc = t[w<<1|1].lc = t[w<<1].rc = t[w<<1|1].rc = t[w].c;
 66     t[w].c = -1;
 67 }
 68 inline void maintain(int w){
 69     t[w].lc = t[w<<1].lc; t[w].rc = t[w<<1|1].rc;
 70     t[w].s = t[w<<1].s + t[w<<1|1].s - (t[w<<1].rc == t[w<<1|1].lc);
 71 }
 72 void build(int u,int v,int w){
 73     t[w].l = u; t[w].r = v; t[w].c = -1; t[w].s = 1;
 74     if (u == v) return;
 75     int mid = (u + v) >> 1;
 76     build(u,mid,w<<1); build(mid+1,v,w<<1|1);
 77 }
 78 void change(int u,int v,int w,int x){
 79     pushdown(w);
 80     if (u == t[w].l && v == t[w].r){
 81         t[w].c = t[w].lc = t[w].rc = x; 
 82         t[w].s = 1; return;
 83     }
 84     int mid = (t[w].l + t[w].r) >> 1;
 85     if (v <= mid) change(u,v,w<<1,x);
 86     else if (u > mid) change(u,v,w<<1|1,x);
 87     else{
 88         change(u,mid,w<<1,x);
 89         change(mid+1,v,w<<1|1,x);
 90     }
 91     maintain(w);
 92 }
 93 int queryseg(int u,int v,int w){
 94     pushdown(w);
 95     if (u == t[w].l && v == t[w].r) return t[w].s;
 96     int mid = (t[w].l + t[w].r) >> 1;
 97     if (v <= mid) return queryseg(u,v,w<<1);
 98     else if (u > mid) return queryseg(u,v,w<<1|1);
 99     else{
100         int ret = queryseg(u,mid,w<<1) + queryseg(mid+1,v,w<<1|1);
101         if (t[w<<1].rc == t[w<<1|1].lc) ret--;
102         return ret;
103     }
104 }
105 int find(int x,int w){
106     pushdown(w);
107     if (t[w].l == t[w].r) return t[w].lc;
108     int mid = (t[w].l + t[w].r) >> 1;
109     if (x <= mid) return find(x,w<<1);
110     else return find(x,w<<1|1);
111 }
112 void modify(int x,int y,int z){
113     while (belong[x] != belong[y]){
114         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
115         change(pos[belong[x]],pos[x],1,z);
116         x = fa[belong[x]];
117     }
118     if (depth[x] < depth[y]) swap(x,y);
119     change(pos[y],pos[x],1,z);
120 }
121 int query(int x,int y){
122     int ret = 0;
123     while (belong[x] != belong[y]){
124         if (depth[belong[x]] < depth[belong[y]]) swap(x,y);
125         ret += queryseg(pos[belong[x]],pos[x],1);
126         if (find(pos[belong[x]],1) == find(pos[fa[belong[x]]],1)) ret--;
127         x = fa[belong[x]];
128     }
129     if (depth[x] < depth[y]) swap(x,y);
130     ret += queryseg(pos[y],pos[x],1);
131     return ret;
132 }
133 int main(){
134     n = read(); m = read(); clr(last,0); pt = edge;
135     rep(i,1,n) c[i] = read();
136     rep(i,1,n-1){
137         x = read(); y = read();
138         addedge(x,y); addedge(y,x);
139     }
140     depth[1] = 0; dfs1(1); dfs2(1,1); build(1,n,1);
141     rep(i,1,n) change(pos[i],pos[i],1,c[i]);
142     rep(i,1,m){
143         scanf("%s",op);
144         switch(op[0]){
145             case 'C':
146                 x = read(); y = read(); z = read();
147                 modify(x,y,z);
148             break;
149             case 'Q':
150                 x = read(); y = read();
151                 printf("%d\n",query(x,y));
152             break;
153         }
154     }
155     return 0;
156 }
View Code

 

posted on 2015-12-16 20:32  ACMICPC  阅读(930)  评论(1编辑  收藏  举报

导航