bzoj2243: [SDOI2011]染色--线段树+树链剖分
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj2243: [SDOI2011]染色--线段树+树链剖分相关的知识,希望对你有一定的参考价值。
此题代码量较大。。但是打起来很爽
原本不用lca做一直wa不知道为什么。。
后来改lca重打了一遍= =结果一遍就AC了orz
题目比较裸,也挺容易打,主要是因为思路可以比较清晰
另:加读入优化比没加快了1.3s。。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 using namespace std; 5 const int maxn = 100010; 6 struct node{ 7 int l,r,lc,rc,sum,lz; 8 }t[maxn*4]; 9 struct edge{ 10 int to,next; 11 }e[maxn*2]; 12 int n,m,u,v,tot,cnt,logn=0; 13 int head[maxn],son[maxn],pre[maxn],tree[maxn],top[maxn],dep[maxn],fa[maxn][30],size[maxn],col[maxn]; 14 15 inline void read(int &x){ 16 char cc=getchar(); x=0; int f=1; 17 while (cc<‘0‘ || cc>‘9‘){if (cc==‘-‘) f=-1; cc=getchar();} 18 while (cc>=‘0‘ && cc<=‘9‘) x=x*10+cc-‘0‘,cc=getchar(); x*=f; 19 } 20 21 inline void insert(int u, int v){ 22 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; 23 } 24 25 inline void dfs1(int u, int f, int d){ 26 size[u]=1; fa[u][0]=f; dep[u]=d; 27 for (int i=1; i<=logn; i++) fa[u][i]=fa[fa[u][i-1]][i-1]; 28 for (int i=head[u]; i!=-1; i=e[i].next){ 29 int v=e[i].to; 30 if (v==f) continue; 31 dfs1(v,u,d+1); 32 size[u]+=size[v]; 33 if (!son[u] || size[v]>size[son[u]]) son[u]=v; 34 } 35 } 36 37 inline void dfs2(int u, int num){ 38 top[u]=num; tree[u]=++cnt; 39 pre[cnt]=u; 40 if (!son[u]) return; 41 dfs2(son[u],num); 42 for (int i=head[u]; i!=-1; i=e[i].next) 43 if (e[i].to!=fa[u][0] && e[i].to!=son[u]) 44 dfs2(e[i].to,e[i].to); 45 } 46 47 inline int lca(int u, int v){ 48 if (dep[u]>dep[v]) swap(u,v); 49 while (dep[u]<dep[v]){ 50 for (int i=logn; i>=0; i--) 51 if (dep[u]<dep[fa[v][i]]) 52 v=fa[v][i]; 53 v=fa[v][0]; 54 } 55 if (u==v) return u; 56 for (int i=logn; i>=0; i--) 57 if (fa[u][i]!=fa[v][i]){ 58 u=fa[u][i]; 59 v=fa[v][i]; 60 } 61 u=fa[u][0]; 62 return u; 63 } 64 65 inline void pushdown(int x){ 66 if (t[x].lz){ 67 t[x<<1].lz=t[x<<1|1].lz=t[x].lz; 68 t[x<<1].lc=t[x<<1].rc=t[x<<1|1].lc=t[x<<1|1].rc=t[x].lz; 69 t[x<<1].sum=t[x<<1|1].sum=1; 70 t[x].lz=0; 71 } 72 } 73 74 inline void pushup(int x){ 75 t[x].lc=t[x<<1].lc; t[x].rc=t[x<<1|1].rc; 76 t[x].sum=t[x<<1].sum+t[x<<1|1].sum-(t[x<<1].rc==t[x<<1|1].lc); 77 } 78 79 inline int query(int a, int b, int x){ 80 int l=t[x].l, r=t[x].r; 81 if (a==l && r==b) return t[x].sum; 82 int mid=l+r>>1; 83 pushdown(x); 84 if (b<=mid) return query(a,b,x<<1); 85 else if (a>mid) return query(a,b,x<<1|1); 86 else return query(a,mid,x<<1)+query(mid+1,b,x<<1|1)-(t[x<<1].rc==t[x<<1|1].lc); 87 } 88 89 inline void update(int a, int b, int c, int x){ 90 int l=t[x].l, r=t[x].r; 91 if (a==l && r==b){ 92 t[x].lc=t[x].rc=t[x].lz=c; 93 t[x].sum=1; 94 return; 95 } 96 int mid=l+r>>1; 97 pushdown(x); 98 if (b<=mid) update(a,b,c,x<<1); 99 else if (a>mid) update(a,b,c,x<<1|1); 100 else{ 101 update(a,mid,c,x<<1); 102 update(mid+1,b,c,x<<1|1); 103 } 104 pushup(x); 105 } 106 107 inline int get_col(int a, int x){ 108 int l=t[x].l, r=t[x].r; 109 if (l==r) return t[x].lc; 110 pushdown(x); 111 int mid=l+r>>1; 112 if (a<=mid) return get_col(a,x<<1); 113 else return get_col(a,x<<1|1); 114 } 115 116 inline void build(int l, int r, int x){ 117 t[x].l=l; t[x].r=r; 118 if (l==r){ 119 t[x].lc=t[x].rc=col[pre[l]]; 120 t[x].sum=1; 121 return; 122 } 123 int mid=l+r>>1; 124 if (l<=mid) build(l,mid,x<<1); 125 if (r>mid) build(mid+1,r,x<<1|1); 126 pushup(x); 127 } 128 129 inline void change(int x, int f, int c){ 130 while (top[x]!=top[f]){ 131 update(tree[top[x]],tree[x],c,1); 132 x=fa[top[x]][0]; 133 } 134 update(tree[f],tree[x],c,1); 135 } 136 137 inline int get_sum(int x, int f){ 138 int res=0; 139 while (top[x]!=top[f]){ 140 res+=query(tree[top[x]],tree[x],1); 141 if (get_col(tree[top[x]],1)==get_col(tree[fa[top[x]][0]],1)) res--; 142 x=fa[top[x]][0]; 143 } 144 res+=query(tree[f],tree[x],1); 145 return res; 146 } 147 148 int main(){ 149 read(n); read(m); 150 while ((1<<logn)<n) logn++; 151 for (int i=1; i<=n; i++) read(col[i]),col[i]++; 152 tot=-1; memset(head,-1,sizeof(head)); 153 for (int i=1; i<n; i++){ 154 read(u); read(v); 155 insert(u,v); insert(v,u); 156 } 157 cnt=0; 158 dfs1(1,0,1); dfs2(1,0); 159 build(1,n,1); 160 char s[5]; 161 while (m--){ 162 scanf("%s", s); 163 if (s[0]==‘Q‘){ 164 read(u); read(v); 165 int t=lca(u,v); 166 printf("%d\n", get_sum(u,t)+get_sum(v,t)-1); 167 } 168 else{ 169 int color; 170 read(u); read(v); read(color); 171 int t=lca(u,v); 172 color++; 173 change(u,t,color); 174 change(v,t,color); 175 } 176 } 177 return 0; 178 }
以上是关于bzoj2243: [SDOI2011]染色--线段树+树链剖分的主要内容,如果未能解决你的问题,请参考以下文章