• 【模板】树链剖分


    洛谷3384

      1 #include<cstdio>
      2 #include<algorithm>
      3 #define ls (cur<<1)
      4 #define rs (cur<<1|1)
      5 #define len(x) (a[x].r-a[x].l+1)
      6 #define mid ((a[cur].l+a[cur].r)>>1) 
      7 using namespace std;
      8 const int maxn=500010;
      9 int n,m,Mod,k,x,y,z,root,tot=0,num=0;
     10 int v[maxn],pos[maxn],dfn[maxn],dep[maxn],son[maxn],size[maxn],fa[maxn],top[maxn],last[maxn];
     11 struct edge{int to,pre;}e[maxn];
     12 struct tree{int l,r,sum,del;}a[maxn<<2];
     13 inline void read(int &k){
     14     k=0; int f=1; char c=getchar();
     15     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
     16     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
     17     k*=f;
     18 }
     19 inline void MOD(int &k){if (k>=Mod) k-=Mod;}
     20 inline void add(int x,int y){e[++tot].to=y; e[tot].pre=last[x]; last[x]=tot;}
     21 void dfs1(int x){
     22     size[x]=1; dep[x]=dep[fa[x]]+1;
     23     for (int i=last[x],to;i;i=e[i].pre)
     24     if ((to=e[i].to)!=fa[x]){
     25         fa[to]=x; dfs1(to);
     26         size[x]+=size[to];
     27         if (size[to]>size[son[x]]) son[x]=to;
     28     }
     29 }
     30 void dfs2(int x,int tp){
     31     top[x]=tp; dfn[x]=++num; pos[num]=x;
     32     if (son[x]) dfs2(son[x],tp);
     33     for (int i=last[x],to;i;i=e[i].pre)
     34     if ((to=e[i].to)!=fa[x]&&to!=son[x]) dfs2(to,to);
     35 }
     36 void build(int cur,int l,int r){
     37     a[cur].l=l; a[cur].r=r;
     38     if (l<r){
     39         build(ls,l,mid); build(rs,mid+1,r);
     40         a[cur].sum=a[ls].sum+a[rs].sum,MOD(a[cur].sum);
     41     }
     42     else a[cur].sum=v[pos[l]];
     43 }
     44 void pushdown(int cur){
     45     if (a[cur].del==0) return; int D=a[cur].del;
     46     a[ls].del+=D;MOD(a[ls].del); a[ls].sum=(a[ls].sum+len(ls)*D)%Mod;
     47     a[rs].del+=D;MOD(a[rs].del); a[rs].sum=(a[rs].sum+len(rs)*D)%Mod;
     48     a[cur].del=0;
     49 }
     50 void add(int cur,int l,int r,int delta){
     51     if (l<=a[cur].l&&a[cur].r<=r){
     52         a[cur].del=(a[cur].del+delta)%Mod;
     53         a[cur].sum=(a[cur].sum+len(cur)*delta)%Mod; return;  
     54     }
     55     pushdown(cur);
     56     if (l<=mid) add(ls,l,r,delta);
     57     if (r>mid) add(rs,l,r,delta);
     58     a[cur].sum=a[ls].sum+a[rs].sum; MOD(a[cur].sum);
     59 }
     60 int query(int cur,int l,int r){
     61     if (l<=a[cur].l&&a[cur].r<=r) return a[cur].sum;
     62     pushdown(cur); int ret=0;
     63     if (l<=mid) ret+=query(ls,l,r),MOD(ret); 
     64     if (r>mid) ret+=query(rs,l,r),MOD(ret);
     65     return ret;
     66 }
     67 int main(){
     68     read(n); read(m); read(root); read(Mod);
     69     for (int i=1;i<=n;i++) read(v[i]),v[i]%=Mod;
     70     for (int i=1;i<n;i++) read(x),read(y),add(x,y),add(y,x);
     71     dfs1(root); dfs2(root,root); build(1,1,n);
     72     for (int i=1;i<=m;i++){
     73         read(k);
     74         if (k==1){
     75             read(x); read(y); read(z);
     76             while(top[x]!=top[y]){
     77                 if (dep[top[x]]<dep[top[y]]) swap(x,y);
     78                 add(1,dfn[top[x]],dfn[x],z); x=fa[top[x]];
     79             }
     80             if (dep[x]>dep[y]) swap(x,y);
     81             add(1,dfn[x],dfn[y],z);
     82         }
     83         if (k==2){
     84             read(x); read(y); int ans=0;
     85             while(top[x]!=top[y]){
     86                 if (dep[top[x]]<dep[top[y]]) swap(x,y);
     87                 ans+=query(1,dfn[top[x]],dfn[x]); MOD(ans); x=fa[top[x]];
     88             }
     89             if (dep[x]>dep[y]) swap(x,y); ans+=query(1,dfn[x],dfn[y]); MOD(ans);
     90             printf("%d
    ",ans);
     91         } 
     92         if (k==3){
     93             read(x); read(y);
     94             add(1,dfn[x],dfn[x]+size[x]-1,y);
     95         }
     96         if (k==4){
     97             read(x);
     98             printf("%d
    ",query(1,dfn[x],dfn[x]+size[x]-1));
     99         }
    100     }
    101     return 0;
    102 }
    View Code
  • 相关阅读:
    Mysql 怎么限制 IP 访问?
    LA2965 n个数中选出最多个数异或和为0
    UVALive 2678 大于s的最短子序列和
    UVA 1193 区间相关(greedy)
    UVA 11992 线段树
    UVA 1400 线段树
    NBUT 1120 线段树
    最大连续区间和的算法总结(转)
    hiho 1015 KMP
    hiho#1128 : 二分·二分查找
  • 原文地址:https://www.cnblogs.com/DriverLao/p/7799721.html
Copyright © 2020-2023  润新知