zoukankan      html  css  js  c++  java
  • BZOJ3589: 动态树

    3589: 动态树

    Time Limit: 30 Sec  Memory Limit: 1024 MB
    Submit: 174  Solved: 79
    [Submit][Status]

    Description

      小明在楼下种了一棵动态树, 该树每天会在某些节点上长出一些果子. 这棵树的根节点为1, 它有n个节点, n-1条边.

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

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

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

      初始时, 每个节点上都没有果子.

    Input

      第一行一个整数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的结果.

    Output

      对于每个事件1, 输出询问的果子数.

    Sample Input


    5
    1 2
    2 3
    2 4
    1 5
    3
    0 1 1
    0 2 3
    1 2 3 1 1 4

    Sample Output

    13

    HINT

     1 <= n <= 200,000, 1 <= nQ <= 200,000, K = 5.


    生成每个树枝的过程是这样的:先在树中随机找一个节点, 然后在这个节点到根的路径上随机选一个节点, 这两个节点就作为树枝的两端.

    Source

    题解:
    各种逗逼。。。
    一个暴力的思路是我们每次沿边走然后打上标记,最后输出有标记的点的和。这样是可以过的。
    然后我写完之后狂WA不止。。。
    对排了几组发现两个标记下传的顺序搞反了。。。T_T
    代码:
      1 #include<cstdio>
      2 
      3 #include<cstdlib>
      4 
      5 #include<cmath>
      6 
      7 #include<cstring>
      8 
      9 #include<algorithm>
     10 
     11 #include<iostream>
     12 
     13 #include<vector>
     14 
     15 #include<map>
     16 
     17 #include<set>
     18 
     19 #include<queue>
     20 
     21 #include<string>
     22 
     23 #define inf 1000000000
     24 
     25 #define maxn 250000+5
     26 
     27 #define maxm 500+100
     28 
     29 #define eps 1e-10
     30 
     31 #define ll long long
     32 
     33 #define pa pair<int,int>
     34 
     35 #define for0(i,n) for(int i=0;i<=(n);i++)
     36 
     37 #define for1(i,n) for(int i=1;i<=(n);i++)
     38 
     39 #define for2(i,x,y) for(int i=(x);i<=(y);i++)
     40 
     41 #define for3(i,x,y) for(int i=(x);i>=(y);i--)
     42 
     43 #define mod 1000000007
     44 
     45 using namespace std;
     46 
     47 inline int read()
     48 
     49 {
     50 
     51     int x=0,f=1;char ch=getchar();
     52 
     53     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
     54 
     55     while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();}
     56 
     57     return x*f;
     58 
     59 }
     60 int n,m,q,tot,head[maxn],a[10],b[10],top[maxn],id[maxn][2],son[maxn],dep[maxn],s[maxn],fa[maxn];
     61 struct edge{int go,next;}e[2*maxn];
     62 struct seg{int l,r,tag[2],sum,ret;}t[4*maxn];
     63 inline void insert(int x,int y)
     64 {
     65     e[++tot]=(edge){y,head[x]};head[x]=tot;
     66     e[++tot]=(edge){x,head[y]};head[y]=tot;
     67 }
     68 inline void dfs(int x)
     69 {
     70     s[x]=1;
     71     for(int i=head[x],y;i;i=e[i].next)
     72         if(!dep[y=e[i].go])
     73         {
     74             dep[y]=dep[x]+1;fa[y]=x;
     75             dfs(y);
     76             s[x]+=s[y];
     77             if(s[y]>s[son[x]])son[x]=y;
     78         }
     79 }
     80 inline void dfs2(int x,int chain)
     81 {
     82     id[x][0]=++m;top[x]=chain;
     83     if(son[x])dfs2(son[x],chain);
     84     for(int i=head[x];i;i=e[i].next)if(e[i].go!=son[x]&&e[i].go!=fa[x])dfs2(e[i].go,e[i].go);
     85     id[x][1]=m;
     86 }
     87 inline void pushup(int k)
     88 {
     89     t[k].sum=t[k<<1].sum+t[k<<1|1].sum;
     90     t[k].ret=t[k<<1].ret+t[k<<1|1].ret;
     91     //cout<<k<<' '<<t[k].sum<<' '<<t[k].ret<<endl;
     92 }
     93 inline void build(int k,int l,int r)
     94 {
     95     t[k].l=l;t[k].r=r;int mid=(l+r)>>1;t[k].tag[0]=-1;
     96     if(l==r)return;
     97     build(k<<1,l,mid);build(k<<1|1,mid+1,r);
     98 }
     99 inline void same(int k,int z)
    100 {
    101     t[k].tag[0]=z;t[k].ret=z==1?t[k].sum:0;
    102 }
    103 inline void update(int k,int z)
    104 {
    105     t[k].tag[1]+=z;t[k].sum+=(t[k].r-t[k].l+1)*z;
    106 }
    107 inline void pushdown(int k)
    108 {
    109     if(t[k].tag[1]){update(k<<1,t[k].tag[1]);update(k<<1|1,t[k].tag[1]);t[k].tag[1]=0;}
    110     if(t[k].tag[0]!=-1){same(k<<1,t[k].tag[0]);same(k<<1|1,t[k].tag[0]);t[k].tag[0]=-1;}
    111 }
    112 inline void change(int k,int x,int y,int z)
    113 {
    114     if(t[k].tag[0]==z)return;
    115     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
    116     if(l==x&&r==y){same(k,z);return;}
    117     pushdown(k);
    118     if(y<=mid)change(k<<1,x,y,z);
    119     else if(x>mid)change(k<<1|1,x,y,z);
    120     else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z);
    121     pushup(k);
    122 }
    123 inline void add(int k,int x,int y,int z)
    124 {
    125     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;
    126     if(l==x&&r==y){update(k,z);return;}
    127     pushdown(k);
    128     if(y<=mid)add(k<<1,x,y,z);
    129     else if(x>mid)add(k<<1|1,x,y,z);
    130     else add(k<<1,x,mid,z),add(k<<1|1,mid+1,y,z);
    131     pushup(k);
    132 }
    133 inline void solve(int x,int y,int z)
    134 {
    135     while(top[x]!=top[y])
    136     {
    137         if(dep[top[x]]<dep[top[y]])swap(x,y);
    138         change(1,id[top[x]][0],id[x][0],z);
    139         x=fa[top[x]];
    140     }
    141     if(dep[x]>dep[y])swap(x,y);
    142     change(1,id[x][0],id[y][0],z);
    143 }
    144 
    145 int main()
    146 
    147 {
    148 
    149     freopen("input.txt","r",stdin);
    150 
    151     freopen("output.txt","w",stdout);
    152 
    153     n=read();
    154     for1(i,n-1)insert(read(),read());
    155     dep[1]=1;dfs(1);dfs2(1,1);
    156     build(1,1,n);
    157     q=read();
    158     while(q--)
    159     {
    160         int ch=read();m=read();
    161         if(!ch)add(1,id[m][0],id[m][1],read());
    162         else 
    163         {
    164             for1(i,m)a[i]=read(),b[i]=read();
    165             for1(i,m)solve(a[i],b[i],1);
    166             printf("%d
    ",t[1].ret&2147483647);
    167             for1(i,m)solve(a[i],b[i],0);
    168         }
    169     }
    170 
    171     return 0;
    172 
    173 } 
    View Code
  • 相关阅读:
    hdu 4002 Find the maximum
    hdu 2837 坑题。
    hdu 3123
    zoj Treasure Hunt IV
    hdu 2053 Switch Game 水题一枚,鉴定完毕
    poj 1430 Binary Stirling Numbers
    hdu 3037 Saving Beans
    hdu 3944 dp?
    南阳oj 求N!的二进制表示最低位的1的位置(从右向左数)。
    fzu 2171 防守阵地 II
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/4142864.html
Copyright © 2011-2022 走看看