BZOJ_2243
给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
题解:
链剖裸题+线段树合并,注意合并的时候分清左右区间端点信息
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <cmath> 5 #include <algorithm> 6 #include <iostream> 7 using namespace std; 8 const int N = 100003; 9 struct tree1 { 10 tree1* lson; 11 tree1* rson; 12 int sum,l,r,color; 13 bool pd; 14 tree1() { 15 lson = rson = NULL; 16 sum = l = r = color = 0; 17 pd = false; 18 } 19 }* root,dizhi[N*3]; 20 int n,m,t; 21 int color[N]; 22 int first[N],to[N*2],next_[N*2],eg; 23 inline void addedge(int x,int y) { 24 next_[++eg] = first[x]; 25 first[x] = eg; 26 to[eg] = y; 27 } 28 inline void add(int x,int y) { 29 addedge(x,y); 30 addedge(y,x); 31 } 32 int fa[N],dep[N],size[N],max_son[N]; 33 inline void dfs1(int u) { 34 size[u] = 1; 35 for(int i = first[u] ; i ; i = next_[i]) { 36 int v = to[i]; 37 if(v==fa[u]) continue; 38 dep[v] = dep[u] + 1; 39 fa[v] = u; 40 dfs1(v); 41 size[u] += size[v]; 42 max_son[u] = size[max_son[u]] > size[v] ? max_son[u] : v; 43 } 44 } 45 int st[N],tt,top[N],hero[N]; 46 inline void dfs2(int u,int ctop) { 47 top[u] = ctop; 48 st[u] = ++tt; 49 hero[tt] = u; 50 if(max_son[u]) dfs2(max_son[u],ctop); 51 for(int i = first[u] ; i ; i = next_[i]) { 52 int v = to[i]; 53 if(v==fa[u] || v==max_son[u]) continue; 54 dfs2(v,v); 55 } 56 } 57 inline void build(tree1* tree,int l,int r) { 58 if(l==r) { 59 tree->sum = 1; 60 tree->l = tree->r = color[hero[l]]; 61 return; 62 } 63 int mid = (l+r)>>1; 64 tree->lson = &dizhi[++t]; 65 tree->rson = &dizhi[++t]; 66 build(tree->lson,l,mid); 67 build(tree->rson,mid+1,r); 68 tree->sum = tree->lson->sum + tree->rson->sum - (tree->lson->r==tree->rson->l); 69 tree->l = tree->lson->l; 70 tree->r = tree->rson->r; 71 } 72 inline void push_down(tree1* tree) { 73 if(tree->pd) { 74 tree->lson->sum = tree->rson->sum = 1; 75 tree->lson->pd = tree->rson->pd = true; 76 tree->lson->l = tree->lson->r = tree->rson->r = tree->rson->l = tree->color; 77 tree->lson->color = tree->rson->color = tree->color; 78 tree->pd = false; 79 } 80 } 81 inline void modify2(tree1* tree,int l,int r,int x,int y,int c) { 82 if(l!=r) push_down(tree); 83 if(x<=l && r<=y) { 84 tree->sum = 1; 85 tree->l = tree->r = c; 86 tree->pd = true; 87 tree->color = c; 88 return; 89 } 90 int mid = (l+r)>>1; 91 if(!(y<l || mid<x)) modify2(tree->lson,l,mid,x,y,c); 92 if(!(y<mid+1||r<x)) modify2(tree->rson,mid+1,r,x,y,c); 93 tree->sum = tree->lson->sum + tree->rson->sum - (tree->lson->r==tree->rson->l); 94 tree->l = tree->lson->l; 95 tree->r = tree->rson->r; 96 } 97 inline void modify(int x,int y,int c) { 98 while(top[x]!=top[y]) { 99 if(dep[top[x]] < dep[top[y]]) swap(x,y); 100 modify2(root,1,n,st[top[x]],st[x],c); 101 x = fa[top[x]]; 102 } 103 if(dep[x] < dep[y]) swap(x,y); 104 modify2(root,1,n,st[y],st[x],c); 105 } 106 struct merge_ { 107 int sum,l,r; 108 merge_(int sum_= 0,int l_= 0,int r_= 0) { 109 sum = sum_;l = l_;r = r_; 110 } 111 }; 112 merge_ query2(tree1* tree,int l,int r,int x,int y) { 113 if(l!=r)push_down(tree); 114 if(x<=l && r<=y) 115 return merge_(tree->sum,tree->l,tree->r); 116 int mid = (l+r)>>1; 117 merge_ q1 = merge_(0,-1,-1); 118 merge_ q2 = merge_(0,-1,-1); 119 if(!(y<l || mid<x)) q1 = query2(tree->lson,l,mid,x,y); 120 if(!(y<mid+1||r<x)) q2 = query2(tree->rson,mid+1,r,x,y); 121 merge_ q3; 122 q3.sum = q1.sum+q2.sum-(q1.r==q2.l); 123 q3.l = q1.l!=-1?q1.l:q2.l; 124 q3.r = q2.r!=-1?q2.r:q1.r; 125 return q3; 126 } 127 inline int query(int x,int y) { 128 merge_ ans1 = merge_(0,-1,-1); 129 merge_ ans2 = merge_(0,-1,-1); 130 while(top[x]!=top[y]) { 131 if(dep[top[x]] < dep[top[y]]) { 132 merge_ linshi = query2(root,1,n,st[top[y]],st[y]); 133 ans2.sum += linshi.sum - (ans2.l==linshi.r); 134 ans2.l = linshi.l; 135 y = fa[top[y]]; 136 } else { 137 merge_ linshi = query2(root,1,n,st[top[x]],st[x]); 138 ans1.sum += linshi.sum - (ans1.l==linshi.r); 139 ans1.l = linshi.l; 140 x = fa[top[x]]; 141 } 142 } 143 if(dep[x] < dep[y]) { 144 merge_ linshi = query2(root,1,n,st[x],st[y]); 145 return linshi.sum + ans1.sum + ans2.sum - (ans1.l==linshi.l) - (ans2.l==linshi.r); 146 } else { 147 merge_ linshi = query2(root,1,n,st[y],st[x]); 148 return linshi.sum + ans1.sum + ans2.sum - (ans1.l==linshi.r) - (ans2.l==linshi.l); 149 } 150 } 151 int main() { 152 scanf("%d%d",&n,&m); 153 for(int i = 1 ; i <= n ; ++i) scanf("%d",&color[i]); 154 for(int i = 1 ; i < n ; ++i) { 155 int x,y; 156 scanf("%d%d",&x,&y); 157 add(x,y); 158 } 159 dfs1(1); 160 dfs2(1,1); 161 root = &dizhi[++t]; 162 build(root,1,n); 163 for(int i = 1 ; i <= m ; ++i) { 164 char haha; 165 int x,y,z; 166 scanf(" %c",&haha); 167 if(haha=='Q') { 168 scanf("%d%d",&x,&y); 169 printf("%d\n",query(x,y)); 170 } else { 171 scanf("%d%d%d",&x,&y,&z); 172 modify(x,y,z); 173 } 174 } 175 }