树链剖分

模板

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<cmath>
  6 using namespace std;
  7 inline int read()
  8 {
  9     char ch=getchar();
 10     int a=0,t=1;
 11     while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}
 12     while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();}
 13     return a*t;
 14 }
 15 inline long long readll()
 16 {
 17     char ch=getchar();
 18     long long a=0,t=1;
 19     while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}
 20     while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();}
 21     return a*t;
 22 }
 23 inline void write(int k){
 24     if (k<0) {
 25         putchar('-');
 26         k=-k;
 27     }
 28     if (k>9) write(k/10);
 29     putchar(k%10+'0');
 30 }
 31 int n,m,r,num=0;
 32 long long p;
 33 int father[500005],dep[500005]={0},son_num[500005];
 34 int heavy_son[500005],id[500005],real[500005];
 35 long long top[500005];
 36 struct tree_arr{
 37     long long sum,tag,l,r;
 38 }tree[500005];
 39 int head[500005],a[500005];
 40 struct edge_arr{
 41     int to,next;
 42 }edge[500005];
 43 inline void lianshi(int u,int v){
 44     num++; edge[num].to=v; edge[num].next=head[u]; head[u]=num;
 45 }
 46 inline void dfs1(int now,int fa){
 47     father[now]=fa; 
 48     dep[now]=dep[father[now]]+1;
 49     son_num[now]=1;
 50     for (int i=head[now];i!=-1;i=edge[i].next){
 51         if (edge[i].to!=father[now]){
 52             dfs1(edge[i].to,now);
 53             son_num[now]+=son_num[edge[i].to];
 54             if (heavy_son[now]<=0 || son_num[heavy_son[now]]<son_num[edge[i].to]){
 55                 heavy_son[now]=edge[i].to;
 56             }
 57         }
 58     }
 59 }
 60 int temp=0;
 61 inline void dfs2(int now,int root){
 62     top[now]=root;
 63     temp++; 
 64     id[now]=temp; 
 65     //printf("%d %d\n",now,id[now]);
 66     real[id[now]]=now;
 67     if (heavy_son[now]<=0) return;
 68     dfs2(heavy_son[now],root);
 69     for (int i=head[now];i!=-1;i=edge[i].next){
 70         if (edge[i].to!=father[now] && edge[i].to!=heavy_son[now]){
 71             dfs2(edge[i].to,edge[i].to);
 72         }
 73     }
 74 }
 75 inline void buildtree(int root,int l,int r){
 76     tree[root].l=l; tree[root].r=r;
 77     if (l==r){
 78         tree[root].sum=a[real[l]]; return;
 79     }
 80     int mid=(l+r)>>1;
 81     buildtree(root*2,l,mid); 
 82     buildtree(root*2+1,mid+1,r);
 83     tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
 84 }
 85 inline void push_down(int root){
 86     tree[root*2].tag+=tree[root].tag; 
 87     tree[root*2].sum+=tree[root].tag*(tree[root*2].r-tree[root*2].l+1);
 88     tree[root*2+1].tag+=tree[root].tag; 
 89     tree[root*2+1].sum+=tree[root].tag*(tree[root*2+1].r-tree[root*2+1].l+1);
 90     tree[root].tag=0;
 91 }
 92 inline void addall(int root,int l,int r,long long x){
 93     if (l>tree[root].r || r<tree[root].l) return;
 94     if (l<=tree[root].l && r>=tree[root].r){
 95         tree[root].tag+=x; tree[root].sum+=x*(tree[root].r-tree[root].l+1);
 96         return;
 97     }
 98     push_down(root);
 99     int mid=(tree[root].l+tree[root].r)>>1;
100     if (r<=mid) addall(root*2,l,r,x);
101     else if (l>mid) addall(root*2+1,l,r,x);
102          else addall(root*2,l,mid,x),addall(root*2+1,mid+1,r,x);
103     tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;
104 }
105 inline void change(int u,int v,long long x){
106     int zuxian_u=top[u],zuxian_v=top[v];
107     while (zuxian_u!=zuxian_v){
108         if (dep[zuxian_u]<dep[zuxian_v]){
109             swap(u,v); swap(zuxian_u,zuxian_v);
110         }
111         addall(1,id[zuxian_u],id[u],x);
112         u=father[zuxian_u]; zuxian_u=top[u];
113     }
114     if (dep[u]>dep[v]){
115         swap(u,v);
116     }
117     addall(1,id[u],id[v],x);
118 }
119 inline long long findsum(int root,int l,int r){
120     if (l>tree[root].r || r<tree[root].l) return 0;
121     if (l<=tree[root].l && r>=tree[root].r){
122         return tree[root].sum;
123     }
124     push_down(root);
125     int mid=(tree[root].l+tree[root].r)>>1;
126     if (r<=mid) return findsum(root*2,l,r);
127     else if (l>mid) return findsum(root*2+1,l,r);
128          else return findsum(root*2,l,mid)+findsum(root*2+1,mid+1,r);
129 }
130 inline long long findans(int u,int v){
131     long long sum=0; int zuxian_u=top[u],zuxian_v=top[v];
132     while (zuxian_u!=zuxian_v){
133         if (dep[zuxian_u]<dep[zuxian_v]){
134             swap(u,v); swap(zuxian_u,zuxian_v);
135         }
136         sum+=findsum(1,id[zuxian_u],id[u]);        
137         sum%=p; 
138         u=father[zuxian_u];
139         zuxian_u=top[u];
140     }
141     if (dep[u]>dep[v]){
142         swap(u,v);
143     }
144     sum+=findsum(1,id[u],id[v]);
145     sum%=p;
146     return sum;
147 }
148 int main(){
149     n=read(),m=read(),r=read(),p=readll();
150     for (int i=1;i<=n;i++) a[i]=read(),head[i]=-1;
151     for (int i=1;i<n;i++){
152         int u=read(),v=read(); lianshi(u,v); lianshi(v,u);
153     } 
154     dep[0]=0; son_num[0]=-1;
155     dfs1(r,0); 
156     dfs2(r,r);
157     /*for (int i=1;i<=n;i++){
158         printf("%d %d %d %d %d %d %d\n",i,father[i],dep[i],son_num[i],heavy_son[i],top[i],id[i]);
159     }
160     return 0;*/
161     
162     buildtree(1,1,temp);
163     
164     for (int i=1;i<=m;i++){
165         int k=read();
166         if (k==1){
167             int x=read(),y=read(),z=readll(); change(x,y,z);
168         }
169         if (k==2){
170             int x=read(),y=read(); printf("%lld\n",findans(x,y)%p);
171         }
172         if (k==3){
173             int x=read(),y=readll(); addall(1,id[x],id[x]+son_num[x]-1,y);
174         }
175         if (k==4){
176             int x=read(); printf("%lld\n",findsum(1,id[x],id[x]+son_num[x]-1)%p);
177         }
178     }
179     return 0;
180 }

 

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<cmath>using namespace std;inline int read(){    char ch=getchar();    int a=0,t=1;    while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}    while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();}    return a*t;}inline long long readll(){    char ch=getchar();    long long a=0,t=1;    while(ch<'0'||ch>'9') {if(ch=='-') t=-1;ch=getchar();}    while(ch<='9'&&ch>='0') {a=a*10+ch-'0';ch=getchar();}    return a*t;}inline void write(int k){if (k<0) {putchar('-');k=-k;}if (k>9) write(k/10);putchar(k%10+'0');}int n,m,r,num=0;long long p;int father[500005],dep[500005]={0},son_num[500005];int heavy_son[500005],id[500005],real[500005];long long top[500005];struct tree_arr{long long sum,tag,l,r;}tree[500005];int head[500005],a[500005];struct edge_arr{int to,next;}edge[500005];inline void lianshi(int u,int v){num++; edge[num].to=v; edge[num].next=head[u]; head[u]=num;}inline void dfs1(int now,int fa){father[now]=fa; dep[now]=dep[father[now]]+1;son_num[now]=1;for (int i=head[now];i!=-1;i=edge[i].next){if (edge[i].to!=father[now]){dfs1(edge[i].to,now);son_num[now]+=son_num[edge[i].to];if (heavy_son[now]<=0 || son_num[heavy_son[now]]<son_num[edge[i].to]){heavy_son[now]=edge[i].to;}}}}int temp=0;inline void dfs2(int now,int root){top[now]=root;temp++; id[now]=temp; //printf("%d %d\n",now,id[now]);real[id[now]]=now;if (heavy_son[now]<=0) return;dfs2(heavy_son[now],root);for (int i=head[now];i!=-1;i=edge[i].next){if (edge[i].to!=father[now] && edge[i].to!=heavy_son[now]){dfs2(edge[i].to,edge[i].to);}}}inline void buildtree(int root,int l,int r){tree[root].l=l; tree[root].r=r;if (l==r){tree[root].sum=a[real[l]]; return;}int mid=(l+r)>>1;buildtree(root*2,l,mid); buildtree(root*2+1,mid+1,r);tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;}inline void push_down(int root){tree[root*2].tag+=tree[root].tag; tree[root*2].sum+=tree[root].tag*(tree[root*2].r-tree[root*2].l+1);tree[root*2+1].tag+=tree[root].tag; tree[root*2+1].sum+=tree[root].tag*(tree[root*2+1].r-tree[root*2+1].l+1);tree[root].tag=0;}inline void addall(int root,int l,int r,long long x){if (l>tree[root].r || r<tree[root].l) return;if (l<=tree[root].l && r>=tree[root].r){tree[root].tag+=x; tree[root].sum+=x*(tree[root].r-tree[root].l+1);return;}push_down(root);int mid=(tree[root].l+tree[root].r)>>1;if (r<=mid) addall(root*2,l,r,x);else if (l>mid) addall(root*2+1,l,r,x);     else addall(root*2,l,mid,x),addall(root*2+1,mid+1,r,x);tree[root].sum=tree[root*2].sum+tree[root*2+1].sum;}inline void change(int u,int v,long long x){int zuxian_u=top[u],zuxian_v=top[v];while (zuxian_u!=zuxian_v){if (dep[zuxian_u]<dep[zuxian_v]){swap(u,v); swap(zuxian_u,zuxian_v);}addall(1,id[zuxian_u],id[u],x);u=father[zuxian_u]; zuxian_u=top[u];}if (dep[u]>dep[v]){swap(u,v);}addall(1,id[u],id[v],x);}inline long long findsum(int root,int l,int r){if (l>tree[root].r || r<tree[root].l) return 0;if (l<=tree[root].l && r>=tree[root].r){return tree[root].sum;}push_down(root);int mid=(tree[root].l+tree[root].r)>>1;if (r<=mid) return findsum(root*2,l,r);else if (l>mid) return findsum(root*2+1,l,r);     else return findsum(root*2,l,mid)+findsum(root*2+1,mid+1,r);}inline long long findans(int u,int v){long long sum=0; int zuxian_u=top[u],zuxian_v=top[v];while (zuxian_u!=zuxian_v){if (dep[zuxian_u]<dep[zuxian_v]){swap(u,v); swap(zuxian_u,zuxian_v);}sum+=findsum(1,id[zuxian_u],id[u]);sum%=p; u=father[zuxian_u];zuxian_u=top[u];}if (dep[u]>dep[v]){swap(u,v);}sum+=findsum(1,id[u],id[v]);sum%=p;return sum;}int main(){    n=read(),m=read(),r=read(),p=readll();for (int i=1;i<=n;i++) a[i]=read(),head[i]=-1;for (int i=1;i<n;i++){int u=read(),v=read(); lianshi(u,v); lianshi(v,u);} dep[0]=0; son_num[0]=-1;dfs1(r,0); dfs2(r,r);/*for (int i=1;i<=n;i++){printf("%d %d %d %d %d %d %d\n",i,father[i],dep[i],son_num[i],heavy_son[i],top[i],id[i]);}return 0;*/buildtree(1,1,temp);for (int i=1;i<=m;i++){int k=read();if (k==1){int x=read(),y=read(),z=readll(); change(x,y,z);}if (k==2){int x=read(),y=read(); printf("%lld\n",findans(x,y)%p);}if (k==3){int x=read(),y=readll(); addall(1,id[x],id[x]+son_num[x]-1,y);}if (k==4){int x=read(); printf("%lld\n",findsum(1,id[x],id[x]+son_num[x]-1)%p);}}return 0;}

 

posted @ 2017-10-20 08:38  lztlztlzt  阅读(164)  评论(0编辑  收藏  举报