zoukankan      html  css  js  c++  java
  • Tsinsen A1517. 动态树 树链剖分,线段树,子树操作

    A1517. 动态树
    时间限制:3.0s   内存限制:1.0GB   
    总提交次数:227   AC次数:67   平均分:49.52
     
    将本题分享到:
          
       
    试题来源
      中国国家队清华集训 2013-2014 第四天
    问题描述
      小明在楼下种了一棵动态树, 该树每天会在某些节点上长出一些果子. 这棵树的根节点为1, 它有n个节点, n-1条边.

      别忘了这是一棵动态树, 每时每刻都是动态的. 小明要求你在这棵树上维护两种事件

      事件0:
      这棵树长出了一些果子, 即某个子树中的每个节点都会长出K个果子.

      事件1:
      小明希望你求出几条树枝上的果子数. 一条树枝其实就是一个从某个节点到根的路径的一段. 每次小明会选定一些树枝, 让你求出在这些树枝上的节点的果子数的和. 注意, 树枝之间可能会重合, 这时重合的部分的节点的果子只要算一次.

      初始时, 每个节点上都没有果子.
    输入格式
      第一行一个整数n(1<=n<=200,000), 即节点数.
      接下来n-1行, 每行两个数字u, v. 表示果子u和果子v之间有一条直接的边. 节点从1开始编号.
      在接下来一个整数nQ(1<=nQ<=200,000), 表示事件.
      最后nQ行, 每行开头要么是0, 要么是1.
      如果是0, 表示这个事件是事件0. 这行接下来的2个整数u, delta表示以u为根的子树中的每个节点长出了delta个果子.
      如果是1, 表示这个事件是事件1. 这行接下来一个整数K(1<=K<=5), 表示这次询问涉及K个树枝. 接下来K对整数u_k, v_k, 每个树枝从节点u_k到节点v_k. 由于果子数可能非常多, 请输出这个数模2^31的结果.
    输出格式
      对于每个事件1, 输出询问的果子数.
    样例输入
    5
    1 2
    2 3
    2 4
    1 5
    3
    0 1 1
    0 2 3
    1 2 3 1 1 4
    样例输出
    13
    数据规模和约定
      对于测试点1, 有1 <= n <= 2,000, 1 <= nQ <= 2,000, K <=5
      对于测试点{2, 3}, 有1 <= n <= 100,000, 1 <= nQ <= 100,000, K = 1
      对于测试点{4, 5}, 有1 <= n <= 100,000, 1 <= nQ <= 100,000, K <= 2
      对于测试点{6, 7}, 有1 <= n <= 100,000, 1 <= nQ <= 100,000, K <= 3
      对于测试点{8, 9, 10}, 有1 <= n <= 200,000, 1 <= nQ <= 200,000, K = 5.
      同一组类型的数据有梯度.

      生成每个树枝的过程是这样的:先在树中随机找一个节点, 然后在这个节点到根的路径上随机选一个节点, 这两个节点就作为树枝的两端.
     
     
    题解:
    树链剖分+线段树+子树操作
    修改时将链上的点打标记(注意:初始时这个标记要赋为 -1 ,不能赋为 0 ,因为 0 在之后的操作中要用。)然后查询时,将链上的标记的值相加,边加边取余。(好像可以自然溢出,因为给的数为2^31)
    每次询问完要将标记清空。
      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define MOD 2147483648LL
      4 #define MAXN 200010
      5 #define LL long long
      6 struct NODE
      7 {
      8     int begin,end,next;
      9 }edge[MAXN*2];
     10 struct node
     11 {
     12     int left,right;
     13     LL sum,tag,tag1,prey;
     14 }tree[MAXN*4];
     15 int cnt,Head[MAXN],n,deep[MAXN],size[MAXN],P[MAXN][18],pos[MAXN],belong[MAXN],ks[MAXN],js[MAXN],SIZE;
     16 bool vis[MAXN];
     17 void addedge(int bb,int ee)
     18 {
     19     edge[++cnt].begin=bb;edge[cnt].end=ee;edge[cnt].next=Head[bb];Head[bb]=cnt;
     20 }
     21 void addedge1(int bb,int ee)
     22 {
     23     addedge(bb,ee);addedge(ee,bb);
     24 }
     25 int read()
     26 {
     27     int s=0,fh=1;char ch=getchar();
     28     while(ch<'0'||ch>'9'){if(ch=='-')fh=-1;ch=getchar();}
     29     while(ch>='0'&&ch<='9'){s=s*10+(ch-'0');ch=getchar();}
     30     return s*fh;
     31 }
     32 void dfs1(int u)
     33 {
     34     int i,v;
     35     size[u]=1;vis[u]=true;
     36     for(i=Head[u];i!=-1;i=edge[i].next)
     37     {
     38         v=edge[i].end;
     39         if(vis[v]==false)
     40         {
     41             deep[v]=deep[u]+1;
     42             P[v][0]=u;
     43             dfs1(v);
     44             size[u]+=size[v];
     45         }
     46     }
     47 }
     48 void Ycl()
     49 {
     50     int i,j;
     51     for(j=1;(1<<j)<=n;j++)
     52     {
     53         for(i=1;i<=n;i++)
     54         {
     55             if(P[i][j-1]!=-1)P[i][j]=P[P[i][j-1]][j-1];
     56         }
     57     }
     58 }
     59 void dfs2(int u,int chain)
     60 {
     61     int k=0,i,v;
     62     pos[u]=++SIZE;belong[u]=chain;ks[u]=SIZE;
     63     for(i=Head[u];i!=-1;i=edge[i].next)
     64     {
     65         v=edge[i].end;
     66         if(deep[v]>deep[u]&&size[v]>size[k])k=v;
     67     }
     68     if(k==0){js[u]=SIZE;return;}
     69     dfs2(k,chain);
     70     for(i=Head[u];i!=-1;i=edge[i].next)
     71     {
     72         v=edge[i].end;
     73         if(deep[v]>deep[u]&&v!=k)dfs2(v,v);
     74     }
     75     js[u]=SIZE;
     76 }
     77 void Pushup(int k)
     78 {
     79     tree[k].sum=(tree[k*2].sum+tree[k*2+1].sum)%MOD;
     80     tree[k].prey=(tree[k*2].prey+tree[k*2+1].prey)%MOD;
     81 }
     82 void Build(int k,int l,int r)
     83 {
     84     tree[k].left=l;tree[k].right=r;tree[k].tag=-1;/*一定要赋为-1*/tree[k].tag1=0LL;tree[k].sum=0LL;
     85     if(l==r)return;
     86     int mid=(l+r)/2;
     87     Build(k*2,l,mid);Build(k*2+1,mid+1,r);
     88     Pushup(k);
     89 }
     90 void Update(int k,int k1)
     91 {
     92     tree[k].tag=(LL)k1;
     93     tree[k].prey=(tree[k].sum*(LL)k1)%MOD;
     94 }
     95 void Update1(int k,int k1)
     96 {
     97     tree[k].tag1=(tree[k].tag1+(LL)k1)%MOD;
     98     tree[k].sum=(tree[k].sum+((LL)tree[k].right-(LL)tree[k].left+1LL)*(LL)k1)%MOD;
     99 }
    100 void Pushdown(int k)
    101 {
    102     int l=k*2,r=k*2+1;
    103     if(tree[k].tag1!=0LL)
    104     {
    105         Update1(l,tree[k].tag1);
    106         Update1(r,tree[k].tag1);
    107         tree[k].tag1=0LL;
    108     }
    109     if(tree[k].tag!=-1)
    110     {
    111         Update(l,tree[k].tag);
    112         Update(r,tree[k].tag);
    113         tree[k].tag=-1;
    114     }
    115 }
    116 void Add(int k,int l,int r,int A)
    117 {
    118     if(l==tree[k].left&&tree[k].right==r){Update1(k,A);return;}
    119     int mid=(tree[k].left+tree[k].right)/2;
    120     Pushdown(k);
    121     if(r<=mid)Add(k*2,l,r,A);
    122     else if(l>mid)Add(k*2+1,l,r,A);
    123     else {Add(k*2,l,mid,A);Add(k*2+1,mid+1,r,A);}
    124     Pushup(k);
    125 }
    126 void Change(int k,int l,int r,int C)
    127 {
    128     if(tree[k].tag==C)return;
    129     if(l==tree[k].left&&tree[k].right==r){Update(k,C);return;}
    130     int mid=(tree[k].left+tree[k].right)/2;
    131     Pushdown(k);
    132     if(r<=mid)Change(k*2,l,r,C);
    133     else if(l>mid)Change(k*2+1,l,r,C);
    134     else {Change(k*2,l,mid,C);Change(k*2+1,mid+1,r,C);}
    135     Pushup(k);
    136 }
    137 void Solve_change(int x,int fa,int C)
    138 {
    139     while(belong[x]!=belong[fa])
    140     {
    141         //if(deep[belong[x]]<deep[belong[fa]])swap(x,fa);
    142         Change(1,pos[belong[x]],pos[x],C);
    143         x=P[belong[x]][0];
    144     }
    145     //if(deep[x]<deep[fa])swap(x,fa);
    146     Change(1,pos[fa],pos[x],C);
    147 }
    148 int main()
    149 {
    150     int bb,ee,Q,i,zs,s1,s2,s3,j;
    151     n=read();
    152     memset(Head,-1,sizeof(Head));cnt=1;
    153     for(i=1;i<n;i++){bb=read();ee=read();addedge1(bb,ee);}
    154     memset(P,-1,sizeof(P));SIZE=0;
    155     dfs1(1);Ycl();
    156     dfs2(1,1);
    157     Q=read();
    158     Build(1,1,n);
    159     for(i=1;i<=Q;i++)
    160     {
    161         zs=read();
    162         if(zs==0){s1=read();s2=read();Add(1,ks[s1],js[s1],s2);}
    163         else
    164         {
    165             s1=read();
    166             for(j=1;j<=s1;j++)
    167             {
    168                 s2=read();s3=read();
    169                 if(deep[s2]<deep[s3])swap(s2,s3);
    170                 Solve_change(s2,s3,1);
    171                 //printf("%d
    ",tree[1].prey);
    172                 //Update(1,0);
    173             }
    174             printf("%lld
    ",tree[1].prey%MOD);
    175             Update(1,0);
    176         }
    177     }
    178     fclose(stdin);
    179     fclose(stdout);
    180     return 0;
    181 }
  • 相关阅读:
    Bitstream or PCM?
    centos7安装Redis-3.2.8
    【生肉】【不义联盟
    ES6中Map数据结构学习笔记
    机器学习基石入门
    2019/5/9 长难句
    文件遍历选取脚本
    [JS奇怪的世界]No.55 危險小叮嚀:陣列與for in
    OpenGL Panorama Player
    吴裕雄--天生自然MySQL学习笔记:MySQL 连接
  • 原文地址:https://www.cnblogs.com/Var123/p/5379962.html
Copyright © 2011-2022 走看看