zoukankan      html  css  js  c++  java
  • 「LuoguP3384」【模板】树链剖分

    题目描述

    如题,已知一棵包含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≤10,M≤10

    对于70%的数据: N≤10^3,M≤10^3

    对于100%的数据: N≤10^5,M≤10^5

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

    样例说明:

    树的结构如下:

    各个操作如下:

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

    题解

    我也是会树剖的女人了!!!嗷嗷嗷嗷嗷嗷嗷嗷嗷嗷

    模板题嘛QAQ,也没什么好讲的

    剖了之后,对于操作1和2,在求lca的过程中做

    对于操作3和4,直接在dfn[x]和dfn[x]+siz[x]-1上搞事就星了

    其实操作1和2可以用树上前缀和水水水水水水(不对要随时询问好像布星QAQ)

      1 #include<cstdio>
      2 #include<iostream>
      3 using namespace std;
      4 const int MAXN=2e5+7;
      5 int val[MAXN];//点权
      6 //以下建原树
      7 struct emm{
      8     int e,f;
      9 }b[4*MAXN];
     10 int h[MAXN];
     11 int tot=0;
     12 void con(int x,int y)
     13 {
     14     b[++tot].f=h[x];
     15     h[x]=tot;
     16     b[tot].e=y;
     17     b[++tot].f=h[y];
     18     h[y]=tot;
     19     b[tot].e=x;
     20     return;
     21 }
     22 //第一遍dfs
     23 int d[MAXN],fa[MAXN],top[MAXN],z[MAXN],siz[MAXN];
     24 void dfs(int x)
     25 {
     26     siz[x]=1;
     27     top[x]=x;
     28     int mac=0,macc=-1;
     29     for(int i=h[x];i;i=b[i].f)
     30     if(!d[b[i].e])
     31     {
     32         d[b[i].e]=d[x]+1;
     33         fa[b[i].e]=x;
     34         dfs(b[i].e);
     35         siz[x]+=siz[b[i].e];
     36         if(macc<siz[b[i].e]){mac=b[i].e,macc=siz[b[i].e];}
     37     }
     38     z[x]=mac;
     39     top[mac]=x;
     40     return;
     41 }
     42 //第二遍dfs
     43 int q[MAXN],dfn[MAXN];
     44 void dfss(int x)
     45 {
     46     q[++tot]=x;
     47     dfn[x]=tot;
     48     if(z[x])dfss(z[x]);
     49     for(int i=h[x];i;i=b[i].f)
     50     if(fa[b[i].e]==x&&b[i].e!=z[x])
     51     dfss(b[i].e);
     52     return;
     53 }
     54 //找top
     55 int fitop(int x)
     56 {
     57     if(top[x]==x)return x;
     58     return top[x]=fitop(top[x]);
     59 }
     60 //建树完成
     61 int n,m,s;
     62 long long mod;
     63 //以下线段树
     64 struct ahh{
     65     int l,r;
     66     long long v,laz;
     67 }a[8*MAXN];
     68 void build(int i,int ll,int rr)
     69 {
     70     a[i].l=ll;
     71     a[i].r=rr;
     72     if(ll==rr){a[i].v=val[q[ll]];return;}
     73     int mid=(ll+rr)>>1;
     74     build((i<<1),ll,mid);
     75     build(((i<<1)|1),mid+1,rr);
     76     a[i].v=a[(i<<1)].v+a[((i<<1)|1)].v%mod;
     77     return;
     78 }
     79 void add(int i,int ll,int rr,int k)
     80 {
     81     if(a[i].l==ll&&a[i].r==rr)
     82     {a[i].laz+=k;return;}
     83     a[i].v=(long long)a[i].v+(rr-ll+1)*k%mod;
     84     int mid=(a[i].l+a[i].r)>>1;
     85     if(rr<=mid)add((i<<1),ll,rr,k);
     86     else if(mid+1<=ll)add(((i<<1)|1),ll,rr,k);
     87     else {add((i<<1),ll,mid,k);add(((i<<1)|1),mid+1,rr,k);}
     88     return;
     89 }
     90 void pushtag(int i)
     91 {
     92     if(!a[i].laz)return;
     93     a[i].v=(long long)a[i].v+a[i].laz*(a[i].r-a[i].l+1)%mod;
     94     if(a[i].l==a[i].r){a[i].laz=0;return;}
     95     a[(i<<1)].laz+=a[i].laz;
     96     a[((i<<1)|1)].laz+=a[i].laz;
     97     a[i].laz=0;
     98     return;
     99 }
    100 unsigned long long ans;
    101 void find(int i,int ll,int rr)
    102 {
    103     pushtag(i);
    104     if(a[i].l==ll&&a[i].r==rr){ans=(ans+a[i].v)%mod;return;}
    105     int mid=(a[i].l+a[i].r)>>1;
    106     if(rr<=mid)find((i<<1),ll,rr);
    107     else if(ll>=mid+1)find(((i<<1)|1),ll,rr);
    108     else {find((i<<1),ll,mid);find(((i<<1)|1),mid+1,rr);}
    109     return;
    110 }
    111 //
    112 int main()
    113 {
    114     //freopen("a.in","r",stdin);
    115     scanf("%d%d%d%lld",&n,&m,&s,&mod);
    116     for(int i=1;i<=n;++i)
    117     scanf("%d",&val[i]);
    118     for(int i=1;i<n;++i)
    119     {
    120         int x,y;
    121         scanf("%d%d",&x,&y);
    122         con(x,y);
    123     }
    124     d[s]=1;
    125     dfs(s);
    126     tot=0;
    127     dfss(s);
    128     for(int i=1;i<=n;++i)
    129     top[i]=fitop(i);
    130     build(1,1,n);
    131     //run
    132     for(int c=1;c<=m;++c)
    133     {
    134         int opt;
    135         scanf("%d",&opt);
    136         if(opt==1)
    137         {
    138             int x,y,z;
    139             scanf("%d%d%d",&x,&y,&z);
    140             //lca
    141             while(top[x]!=top[y])
    142             {
    143                 if(d[top[x]]>d[top[y]])
    144                 {
    145                     add(1,dfn[top[x]],dfn[x],z);
    146                     x=fa[top[x]];
    147                 }
    148                 else
    149                 {
    150                     add(1,dfn[top[y]],dfn[y],z);
    151                     y=fa[top[y]];
    152                 }
    153             }
    154             if(d[x]>d[y])add(1,dfn[y],dfn[x],z);
    155             else add(1,dfn[x],dfn[y],z);
    156         }
    157         else if(opt==2)
    158         {
    159             int x,y;
    160             scanf("%d%d",&x,&y);
    161             ans=0;
    162             while(top[x]!=top[y])
    163             {
    164                 if(d[top[x]]>d[top[y]])
    165                 {
    166                     find(1,dfn[top[x]],dfn[x]);
    167                     ans%=mod;
    168                     x=fa[top[x]];
    169                 }
    170                 else
    171                 {
    172                     find(1,dfn[top[y]],dfn[y]);
    173                     ans%=mod;
    174                     y=fa[top[y]];
    175                 }
    176             }
    177             if(d[x]>d[y])find(1,dfn[y],dfn[x]);
    178             else find(1,dfn[x],dfn[y]);
    179             printf("%lld
    ",ans%mod);
    180         }
    181         else if(opt==3)
    182         {
    183             int x,z;
    184             scanf("%d%d",&x,&z);
    185             add(1,dfn[x],dfn[x]+siz[x]-1,z);
    186         }
    187         else
    188         {
    189             int x;
    190             scanf("%d",&x);
    191             ans=0;
    192             find(1,dfn[x],dfn[x]+siz[x]-1);
    193             printf("%lld
    ",ans%mod);
    194         }
    195     }
    196     return 0;
    197 }
  • 相关阅读:
    前端基础(2)CSS
    前端基础(1)、HTML
    MySQL数据库,这一篇就够啦!!!(持续更新)
    十、数据库之流程控制
    九、数据库之存储过程和函数
    spring注解总结
    eclipse导入项目后错误的处理方式
    ssm分页查询错误
    字节编址和字的区别(转)
    数据库查询练习
  • 原文地址:https://www.cnblogs.com/qwerta/p/9629817.html
Copyright © 2011-2022 走看看