• 洛谷P3384 【模板】树链剖分


    题目描述

    如题,已知一棵包含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%的数据: N10,M10

    对于70%的数据: N10^3,M10^3

    对于100%的数据: N10^5,M10^5

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

    样例说明:

    树的结构如下:

    各个操作如下:

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

      1 #include<cmath>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #define maxn 100007
      7 using namespace std;
      8 long long read()
      9 {
     10     long long x=0,f=1;
     11     char ch=getchar();
     12     while(ch<'0'||ch>'9')
     13     {
     14         if(ch=='-')
     15             f=-1;
     16         ch=getchar();
     17     }
     18     while(ch>='0'&&ch<='9')
     19     {
     20         x=x*10+ch-'0';
     21         ch=getchar();
     22     }
     23     return x*f;
     24 }
     25 int n,m,num,root,p,opt,x,y,z,cnt;
     26 int head[maxn*2],a[maxn],son[maxn],fa[maxn],deep[maxn],size[maxn],top[maxn],pos[maxn],data[maxn],in[maxn],out[maxn];
     27 struct node
     28 {
     29     int v,nxt;
     30 } e[maxn];
     31 void add(int u,int v)
     32 {
     33     e[++num].v=v;
     34     e[num].nxt=head[u];
     35     head[u]=num;
     36     e[++num].v=u;
     37     e[num].nxt=head[v];
     38     head[v]=num;
     39 }
     40 struct NODE
     41 {
     42     int l,r,sum,flag;
     43 } tree[maxn*4];
     44 void dfs(int now)
     45 {
     46     size[now]=1;
     47     for(int i=head[now]; i; i=e[i].nxt)
     48         if(fa[now]!=e[i].v)
     49         {
     50             fa[e[i].v]=now;
     51             deep[e[i].v]=deep[now] + 1;
     52             dfs(e[i].v);
     53             size[now]+=size[e[i].v];
     54             if(size[son[now]]<size[e[i].v])
     55                 son[now]=e[i].v;
     56         }
     57 }
     58 void DFS(int now,int num)
     59 {
     60     top[now]=num;
     61     pos[now]=++cnt;
     62     in[now]=cnt;
     63     data[cnt]=a[now];
     64     if(son[now])
     65         DFS(son[now],num);
     66     for(int i=head[now]; i; i=e[i].nxt)
     67         if(fa[now]!=e[i].v&&e[i].v!=son[now])
     68             DFS(e[i].v,e[i].v);
     69     out[now]=cnt;
     70 }
     71 void build(int now,int l,int r)
     72 {
     73     tree[now].l=l;
     74     tree[now].r=r;
     75     tree[now].flag=0;
     76     if(l==r)
     77     {
     78         tree[now].sum=data[l];
     79         return ;
     80     }
     81     int mid=(l+r)>>1;
     82     build(now<<1,l,mid);
     83     build(now<<1|1,mid+1,r);
     84     tree[now].sum=tree[now<<1].sum+tree[now<<1|1].sum;
     85 }
     86 void down(int now)
     87 {
     88     if(tree[now].l==tree[now].r)
     89     {
     90         tree[now].flag=0;
     91         return ;
     92     }
     93     tree[now<<1].flag+=tree[now].flag;
     94     tree[now<<1|1].flag+=tree[now].flag;
     95     tree[now<<1].sum=(tree[now<<1].sum+tree[now].flag*(tree[now<<1].r-tree[now<<1].l+1))%p;
     96     tree[now<<1|1].sum=(tree[now<<1|1].sum+tree[now].flag*(tree[now<<1|1].r-tree[now<<1|1].l+1))%p;
     97     tree[now].flag=0;
     98 }
     99 void change(int now,int l,int r,int f)
    100 {
    101     while(tree[now].flag)
    102         down(now);
    103     if(tree[now].l>r||tree[now].r<l)
    104         return ;
    105     if(tree[now].l>=l&&tree[now].r<=r)
    106     {
    107         tree[now].flag=f;
    108         (tree[now].sum+=f*(tree[now].r-tree[now].l+1))%=p;
    109         return ;
    110     }
    111     change(now<<1,l,r,f);
    112     change(now<<1|1,l,r,f);
    113     tree[now].sum=(tree[now<<1].sum+tree[now<<1|1].sum)%p;
    114 }
    115 int query(int now,int l,int r)
    116 {
    117     while(tree[now].flag) down(now);
    118     if(tree[now].l>r||tree[now].r<l)
    119         return 0;
    120     if(tree[now].l>=l&&tree[now].r<=r)
    121         return tree[now].sum;
    122     return (query(now<<1,l,r)+query(now<<1|1,l,r))%p;
    123 }
    124 void add1()
    125 {
    126     x=read(),y=read(),z=read(),z%=p;
    127     while(top[x]!=top[y])
    128     {
    129         if(deep[top[x]]<deep[top[y]])
    130             swap(x,y);
    131         change(1,pos[top[x]],pos[x],z);
    132         x=fa[top[x]];
    133     }
    134     if(deep[x]<deep[y])
    135         swap(x,y);
    136     change(1,pos[y],pos[x],z);
    137 }
    138 void add2()
    139 {
    140     x=read(),z=read(),z%=p;
    141     change(1,in[x],out[x],z);
    142 }
    143 void query1()
    144 {
    145     x=read(),y=read();
    146     int ans=0;
    147     while(top[x]!=top[y])
    148     {
    149         if(deep[top[x]]<deep[top[y]])
    150             swap(x,y);
    151         ans=(ans+query(1,pos[top[x]],pos[x]))%p;
    152         x=fa[top[x]];
    153     }
    154     if(deep[x]<deep[y])
    155         swap(x,y);
    156     (ans+=query(1,pos[y],pos[x]))%=p;
    157     printf("%d\n",ans);
    158 }
    159 void query2()
    160 {
    161     x=read();
    162     int ans=0;
    163     (ans=query(1,in[x],out[x]))%=p;
    164     printf("%d\n",ans);
    165 }
    166 int main()
    167 {
    168     n=read(),m=read(),root=read(),p=read();
    169     for(int i=1; i<=n; ++i)
    170         a[i]=read(),a[i]%=p;
    171     for(int i=1,a,b; i<n; ++i)
    172         a=read(),b=read(),add(a,b);
    173     dfs(root);
    174     DFS(root,root);
    175     build(1,1,n);
    176     while(m--)
    177     {
    178         opt=read();
    179         if(opt==1)
    180             add1();
    181         else if(opt==3)
    182             add2();
    183         else if(opt==2)
    184             query1();
    185         else
    186             query2();
    187     }
    188     return 0;
    189 }
    View Code
  • 相关阅读:
    ajax原理和XmlHttpRequest对象
    在vue项目中 如何定义全局变量 全局函数
    杂乱知识 -- 记录工作或学习中遇到的一些点
    JavaScript中的数组遍历forEach()与map()方法以及兼容写法
    cookie的存取删
    微信小程序中公用内容
    mysql 多实例
    yum 安装和卸载
    rpm 安装卸载
    git blame
  • 原文地址:https://www.cnblogs.com/liweilin/p/10187821.html
Copyright © 2020-2023  润新知