洛谷 P3384 【模板】树链剖分 如题

 

P3384 【模板】树链剖分

  • 时空限制1s / 128MB

题目描述

如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作:

操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z

操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和

操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z

操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和

输入输出格式

输入格式:

 

第一行包含4个正整数N、M、R、P,分别表示树的结点个数、操作个数、根节点序号和取模数(即所有的输出结果均对此取模)。

接下来一行包含N个非负整数,分别依次表示各个节点上初始的数值。

接下来N-1行每行包含两个整数x、y,表示点x和点y之间连有一条边(保证无环且连通)

接下来M行每行包含若干个正整数,每行表示一个操作,格式如下:

操作1: 1 x y z

操作2: 2 x y

操作3: 3 x z

操作4: 4 x

 

输出格式:

 

输出包含若干行,分别依次表示每个操作2或操作4所得的结果(对P取模)

 

输入输出样例

输入样例#1:
5 5 2 24
7 3 7 8 0 
1 2
1 5
3 1
4 1
3 4 2
3 2 2
4 5
1 5 1 3
2 1 3
输出样例#1:
2
21

说明

时空限制:1s,128M

数据规模:

对于30%的数据: N \leq 10, M \leq 10N10,M10

对于70%的数据: N \leq {10}^3, M \leq {10}^3N103,M103

对于100%的数据: N \leq {10}^5, M \leq {10}^5N105,M105

( 其实,纯随机生成的树LCA+暴力是能过的,可是,你觉得可能是纯随机的么233 )

样例说明:

树的结构如下:

各个操作如下:

故输出应依次为2、21(重要的事情说三遍:记得取模)

-------------------------------------------------------------------------------------------------------------

树链剖分就是把在原树上的操作转化为在线段树上操作

对于操作一、三,我们把它变成区间加;

对于操作二、四,变成区间求和。

特别的,对于操作三、四

因为原树上的点的映射pos(其实就是给原树结点重新编号)有着连续性:

       一个结点的父节点一定小于这个结点,且是连续的

       所以一颗子树中所有的点都比根节点大,且是连续的

 所以可以放到线段树上操作

比如映射点pos[x]的子树,在线段树上的区间为pos[x]到pos[x]+size[x]-1    //size[x]表示以x为根节点的子树拥有的结点总数

 

感觉比   这题   要难?

存板子:

 

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<iostream>
  4 #define maxn 233333
  5 using namespace std;
  6 struct node{int to,next;};
  7 struct rode{int l,r,sum,tag;};
  8 node e[maxn<<1];
  9 rode tr[maxn<<2];
 10 int read();
 11 int n,m,r,p,pre[maxn],cnt,v[maxn],fa[maxn],dep[maxn],size[maxn],poi,pos[maxn],bl[maxn];
 12 int solvelsum(int,int);
 13 void ladd(int,int,int);
 14 void add(int,int,int,int);
 15 int querysum(int,int,int);
 16 void pushdown(int);
 17 void pushup(int);
 18 void change(int,int,int);
 19 void build(int,int,int);
 20 void dfs1(int);
 21 void dfs2(int,int);
 22 void ins(int,int);
 23 int main(){
 24     n=read();m=read();r=read();p=read();
 25     for(int i=1;i<=n;i++) v[i]=read();
 26     cnt=0;poi=0;
 27     for(int i=1;i<n;i++){
 28         int x=read(),y=read();
 29         ins(x,y);
 30     }
 31     fa[r]=r;dep[r]=1;
 32     dfs1(r);
 33     dfs2(r,r);
 34     build(1,n,1);
 35     for(int i=1;i<=n;i++) change(pos[i],v[i],1);
 36     for(int i=1;i<=m;i++){
 37         int o=read();
 38         if(o==1){
 39             int x=read(),y=read(),z=read();
 40             ladd(x,y,z);
 41         }
 42         else if(o==2){
 43             int x=read(),y=read(); 
 44             printf("%d\n",solvelsum(x,y));
 45         }
 46         else if(o==3){
 47             int x=read(),y=read();
 48             add(pos[x],pos[x]+size[x]-1,y,1);
 49         }
 50         else{
 51             int x=read();
 52             printf("%d\n",querysum(pos[x],pos[x]+size[x]-1,1));
 53         }
 54     }
 55     return 0;
 56 }
 57 #define lson ro<<1
 58 #define rson ro<<1|1
 59 int solvelsum(int x,int y){
 60     int sum=0;
 61     while(bl[x]!=bl[y]){
 62         if(dep[bl[x]]<dep[bl[y]]) swap(x,y);
 63         sum=(sum+querysum(pos[bl[x]],pos[x],1))%p;
 64         x=fa[bl[x]];
 65     }
 66     if(pos[x]>pos[y]) swap(x,y);
 67     sum=(sum+querysum(pos[x],pos[y],1))%p;
 68     return sum;
 69 }
 70 void ladd(int x,int y,int k){
 71     while(bl[x]!=bl[y]){
 72         if(dep[bl[x]]<dep[bl[y]]) swap(x,y);
 73         add(pos[bl[x]],pos[x],k,1);
 74         x=fa[bl[x]];
 75     }
 76     if(pos[x]>pos[y]) swap(x,y);
 77     add(pos[x],pos[y],k,1);
 78 }
 79 void add(int l,int r,int k,int ro){
 80     if(l<=tr[ro].l&&tr[ro].r<=r){
 81         tr[ro].sum=(tr[ro].sum+(tr[ro].r-tr[ro].l+1)*k)%p;
 82         tr[ro].tag=(tr[ro].tag+k)%p;
 83         return;
 84     }
 85     if(tr[ro].tag) pushdown(ro);
 86     int mid=(tr[ro].l+tr[ro].r)>>1;
 87     if(l<=mid) add(l,r,k,lson);
 88     if(r>mid)  add(l,r,k,rson);
 89     pushup(ro);
 90 }
 91 int querysum(int l,int r,int ro){
 92     if(l<=tr[ro].l&&tr[ro].r<=r) return tr[ro].sum;
 93     if(tr[ro].tag) pushdown(ro);
 94     int mid=(tr[ro].l+tr[ro].r)>>1;
 95     if(l<=mid&&mid<r) return (querysum(l,r,lson)+querysum(l,r,rson))%p;
 96     if(l<=mid) return querysum(l,r,lson);
 97     if(r>mid) return querysum(l,r,rson);
 98 }
 99 void pushdown(int ro){
100     int k=tr[ro].tag;tr[ro].tag=0;
101     tr[lson].tag=(tr[lson].tag+k)%p;
102     tr[rson].tag=(tr[rson].tag+k)%p;
103     tr[lson].sum=(tr[lson].sum+(tr[lson].r-tr[lson].l+1)*k)%p;
104     tr[rson].sum=(tr[rson].sum+(tr[rson].r-tr[rson].l+1)*k)%p;
105 }
106 void pushup(int ro){
107     tr[ro].sum=(tr[lson].sum+tr[rson].sum)%p;
108 }
109 void change(int x,int k,int ro){
110     if(tr[ro].l==tr[ro].r){
111         tr[ro].sum=k%p;
112         return;
113     }
114     int mid=(tr[ro].l+tr[ro].r)>>1;
115     if(x<=mid) change(x,k,lson);
116     else change(x,k,rson);
117     pushup(ro);
118 }
119 void build(int l,int r,int ro){
120     tr[ro].l=l;tr[ro].r=r;
121     if(l==r) return;
122     int mid=(l+r)>>1;
123     build(l,mid,lson);
124     build(mid+1,r,rson);
125 }
126 void dfs2(int x,int chain){
127     int k=0;
128     pos[x]=++poi;
129     bl[x]=chain;
130     for(int i=pre[x];i;i=e[i].next){
131         int to=e[i].to;
132         if(dep[to]>dep[x]&&size[to]>size[k]) k=to;
133     }
134     if(k==0) return;
135     dfs2(k,chain);
136     for(int i=pre[x];i;i=e[i].next){
137         int to=e[i].to;
138         if(dep[to]>dep[x]&&k!=to) dfs2(to,to);
139     }
140 }
141 void dfs1(int x){
142     size[x]=1;
143     for(int i=pre[x];i;i=e[i].next){
144         int to=e[i].to;
145         if(fa[x]!=to){
146             fa[to]=x;
147             dep[to]=dep[x]+1;
148             dfs1(to);
149             size[x]+=size[to];
150         }
151     }
152 }
153 void ins(int x,int y){
154     e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt;
155     e[++cnt].to=x;e[cnt].next=pre[y];pre[y]=cnt;
156 }
157 int read(){
158     int ans=0,f=1;char c=getchar();
159     while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();}
160     while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f;
161 }
树链剖分

 

posted @ 2017-11-10 16:17  lpl_bys  阅读(236)  评论(0编辑  收藏  举报