bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)
今早刷了两道树剖的题目,用时两小时十五分钟= =
树剖的题目代码量普遍120+
其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久
3083:裸树剖+“换根”
所谓换根其实只要判断一下当前询问点的子树和当前根的位置关系就好了,不能真的换根
根不在当前点的子树中则不影响;根在当前子树中,那么根所在的那部分子树不询问就可以了,而其他点都要询问
3626:这个题目很巧妙
有两个地方是很神的,一是将询问l~r转化为询问z一个点,二是离线操作O(qlog2n)就解决了询问
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //bzoj3083 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define INF 1000000010 6 using namespace std; 7 const int maxn = 100010; 8 struct node{ 9 int l,r,lz,mn; 10 }t[maxn*4]; 11 struct edge{ 12 int to,next; 13 }e[maxn*2]; 14 int head[maxn],tot,n,Q,u,v,w,cap,size[maxn],fa[maxn],dep[maxn],top[maxn],son[maxn],tree[maxn],pre[maxn],cnt=0,v0[maxn],opt; 15 16 void insert(int u, int v){ 17 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; 18 } 19 20 void dfs1(int u, int f, int d){ 21 size[u]=1; fa[u]=f; dep[u]=d; 22 for (int i=head[u]; i!=-1; i=e[i].next){ 23 int v=e[i].to; if (v==f) continue; 24 dfs1(v,u,d+1); 25 size[u]+=size[v]; 26 if (!son[u] || size[v]>size[son[u]]) son[u]=v; 27 } 28 } 29 30 void dfs2(int u, int num){ 31 top[u]=num; tree[u]=++cnt; pre[cnt]=u; 32 if (!son[u]) return; 33 dfs2(son[u],num); 34 for (int i=head[u]; i!=-1; i=e[i].next) 35 if (e[i].to!=fa[u] && e[i].to!=son[u]) dfs2(e[i].to,e[i].to); 36 } 37 38 void pushup(int x){ 39 t[x].mn=min(t[x<<1].mn,t[x<<1|1].mn); 40 } 41 42 void pushdown(int x){ 43 if (t[x].lz){ 44 t[x<<1].lz=t[x<<1|1].lz=t[x].lz; 45 t[x<<1].mn=t[x<<1|1].mn=t[x].mn; 46 t[x].lz=0; 47 } 48 } 49 50 void update(int a, int b, int w, int x){ 51 int l=t[x].l, r=t[x].r; 52 if (l==a && r==b){ 53 t[x].lz=1; 54 t[x].mn=w; 55 return; 56 } 57 int mid=l+r>>1; 58 pushdown(x); 59 if (a>mid) update(a,b,w,x<<1|1); 60 else if (b<=mid) update(a,b,w,x<<1); 61 else update(a,mid,w,x<<1),update(mid+1,b,w,x<<1|1); 62 pushup(x); 63 } 64 65 int get_min(int a, int b, int x){ 66 int l=t[x].l, r=t[x].r; 67 if (l==a && b==r) return t[x].mn; 68 int mid=l+r>>1; 69 pushdown(x); 70 if (b<=mid) return get_min(a,b,x<<1); 71 else if (a>mid) return get_min(a,b,x<<1|1); 72 else return min(get_min(a,mid,x<<1),get_min(mid+1,b,x<<1|1)); 73 } 74 75 void build(int l, int r, int x){ 76 t[x].l=l, t[x].r=r; 77 if (l==r){ 78 t[x].mn=v0[pre[l]]; 79 t[x].lz=0; 80 return; 81 } 82 int mid=l+r>>1; 83 if (l<=mid) build(l,mid,x<<1); 84 if (r>mid) build(mid+1,r,x<<1|1); 85 pushup(x); 86 } 87 88 void change(int x, int y, int c){ 89 while (top[x]!=top[y]){ 90 if (dep[x]<dep[y]) swap(x,y); 91 update(tree[top[x]],tree[x],c,1); 92 x=fa[top[x]]; 93 } 94 if (dep[x]>dep[y]) swap(x,y); 95 update(tree[x],tree[y],c,1); 96 } 97 98 int main(){ 99 scanf("%d%d", &n, &Q); tot=1; memset(head,-1,sizeof(head)); cnt=0; 100 for (int i=1; i<n; i++) scanf("%d%d", &u, &v),insert(u,v),insert(v,u); 101 dfs1(1,0,1); 102 dfs2(1,1); 103 for (int i=1; i<=n; i++) scanf("%d", &v0[i]); 104 build(1,cnt,1); 105 scanf("%d", &cap); 106 while (Q--){ 107 scanf("%d", &opt); 108 if (opt==1) scanf("%d", &cap); 109 if (opt==2){ 110 scanf("%d%d%d", &u, &v, &w); 111 change(u,v,w); 112 } 113 if (opt==3){ 114 scanf("%d", &u); 115 if (u==cap) printf("%d\n", t[1].mn); 116 else{ 117 int child=0; 118 for (int i=head[u]; i!=-1; i=e[i].next){ 119 int v=e[i].to; 120 if (v==fa[u]) continue; 121 if (tree[v]<=tree[cap] && tree[cap]<=tree[v]+size[v]-1) child=v; 122 } 123 if (child){ 124 int left=min(INF,get_min(1,tree[child]-1,1)); 125 int right=INF; 126 if (tree[child]+size[child]<=cnt) right=min(right,get_min(tree[child]+size[child],cnt,1)); 127 printf("%d\n", min(min(left,right),get_min(tree[u],tree[u],1))); 128 } 129 else printf("%d\n", get_min(tree[u],tree[u]+size[u]-1,1)); 130 } 131 } 132 } 133 return 0; 134 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 //bzoj3626 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define MOD 201314 6 using namespace std; 7 const int maxn = 50010; 8 struct node{ 9 int l,r,lz,sum,len; 10 }t[maxn*4]; 11 struct edge{ 12 int to,next; 13 }e[maxn*2]; 14 struct Ans{ 15 int z,R,L; 16 }ans[maxn]; 17 struct cover{ 18 int p,id; 19 bool flag; 20 }a[maxn*2]; 21 int fa[maxn],dep[maxn],size[maxn],top[maxn],son[maxn],head[maxn],tot,cnt; 22 int tree[maxn],pre[maxn],n,q,u,v; 23 24 bool cmp(cover a, cover b){ 25 return a.p<b.p; 26 } 27 28 void insert(int u, int v){ 29 e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; 30 } 31 32 void dfs1(int u, int f, int d){ 33 fa[u]=f; dep[u]=d; size[u]=1; 34 for (int i=head[u]; i!=-1; i=e[i].next){ 35 int v=e[i].to; if (v==f) continue; 36 dfs1(v,u,d+1); 37 size[u]+=size[v]; 38 if (!son[u] || size[v]>size[son[u]]) son[u]=v; 39 } 40 } 41 42 void dfs2(int u, int num){ 43 top[u]=num; tree[u]=++cnt; pre[cnt]=u; 44 if (!son[u]) return; 45 dfs2(son[u],num); 46 for (int i=head[u]; i!=-1; i=e[i].next) 47 if (e[i].to!=son[u] && e[i].to!=fa[u]) dfs2(e[i].to,e[i].to); 48 } 49 50 void pushup(int x){ 51 t[x].sum=t[x<<1].sum+t[x<<1|1].sum; 52 } 53 54 void pushdown(int x){ 55 if (t[x].lz){ 56 t[x<<1].lz+=t[x].lz; 57 t[x<<1|1].lz+=t[x].lz; 58 t[x<<1].sum+=t[x<<1].len*t[x].lz; 59 t[x<<1|1].sum+=t[x<<1|1].len*t[x].lz; 60 t[x].lz=0; 61 } 62 } 63 64 int query(int a, int b, int x){ 65 int l=t[x].l, r=t[x].r; 66 if (l==a && r==b) return t[x].sum; 67 int mid=l+r>>1; 68 pushdown(x); 69 if (b<=mid) return query(a,b,x<<1); 70 else if (a>mid) return query(a,b,x<<1|1); 71 else return query(a,mid,x<<1)+query(mid+1,b,x<<1|1); 72 } 73 74 void update(int a, int b, int x){ 75 int l=t[x].l, r=t[x].r; 76 if (l==a && r==b){ 77 t[x].sum+=t[x].len; 78 t[x].lz++; 79 return; 80 } 81 int mid=l+r>>1; 82 pushdown(x); 83 if (b<=mid) update(a,b,x<<1); 84 else if (a>mid) update(a,b,x<<1|1); 85 else update(a,mid,x<<1),update(mid+1,b,x<<1|1); 86 pushup(x); 87 } 88 89 void build(int l, int r, int x){ 90 t[x].l=l, t[x].r=r; t[x].len=r-l+1; 91 if (l==r){ 92 t[x].sum=0; 93 t[x].lz=0; 94 return; 95 } 96 int mid=l+r>>1; 97 if (l<=mid) build(l,mid,x<<1); 98 if (r>mid) build(mid+1,r,x<<1|1); 99 pushup(x); 100 } 101 102 void tree_update(int x, int y){ 103 while (top[x]!=top[y]){ 104 if (dep[x]<dep[y]) swap(x,y); 105 update(tree[top[x]],tree[x],1); 106 x=fa[top[x]]; 107 } 108 if (dep[x]>dep[y]) swap(x,y); 109 update(tree[x],tree[y],1); 110 } 111 112 int tree_query(int x, int y){ 113 int ret=0; 114 while (top[x]!=top[y]){ 115 if (dep[x]<dep[y]) swap(x,y); 116 ret+=query(tree[top[x]],tree[x],1); ret%=MOD; 117 x=fa[top[x]]; 118 } 119 if (dep[x]>dep[y]) swap(x,y); 120 return (query(tree[x],tree[y],1) % MOD +ret) % MOD; 121 } 122 123 int main(){ 124 scanf("%d%d", &n, &q); 125 tot=1; memset(head,-1,sizeof(head)); 126 for (int i=1; i<n; i++){ 127 scanf("%d", &u); 128 insert(u,i); 129 } 130 cnt=0; 131 dfs1(0,0,1); 132 dfs2(0,0); 133 build(1,n,1); 134 cnt=0; 135 for (int i=1; i<=q; i++){ 136 scanf("%d%d%d", &u, &v, &ans[i].z); 137 a[++cnt].p=u-1; a[cnt].id=i; a[cnt].flag=0; 138 a[++cnt].p=v; a[cnt].id=i; a[cnt].flag=1; 139 } 140 sort(a+1,a+1+cnt,cmp); 141 int now=-1; 142 for (int i=1; i<=cnt; i++){ 143 while (now<a[i].p){ 144 now++; 145 tree_update(now,0); 146 } 147 int pos=a[i].id; 148 if (!a[i].flag) ans[pos].L=tree_query(ans[pos].z,0); 149 else ans[pos].R=tree_query(ans[pos].z,0); 150 } 151 for (int i=1; i<=q; i++) printf("%d\n", (ans[i].R-ans[i].L+MOD)%MOD); 152 return 0; 153 }