bzoj3083 遥远的国度 && bzoj3626 LCA (树链剖分)

今早刷了两道树剖的题目,用时两小时十五分钟= =

树剖的题目代码量普遍120+

其实打熟练之后是很容易调的,不熟练的话代码量大可能会因为某些小细节调很久

3083:裸树剖+“换根”

所谓换根其实只要判断一下当前询问点的子树和当前根的位置关系就好了,不能真的换根

根不在当前点的子树中则不影响;根在当前子树中,那么根所在的那部分子树不询问就可以了,而其他点都要询问

3626:这个题目很巧妙

有两个地方是很神的,一是将询问l~r转化为询问z一个点,二是离线操作O(qlog2n)就解决了询问

 

  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 }
View Code
  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 }
View Code

 

posted @ 2016-10-16 11:53  mzl0707  阅读(160)  评论(0编辑  收藏  举报