zoukankan      html  css  js  c++  java
  • bzoj 4034

    我写的是 DFS序+线段树

    DFS序(出去的位置要单独建点)上,进入的位置是权值,出去的位置是权值的相反数,可以证明节点i到根节点的路径上的点的权值和是DFS序上1~in[i]的和。

    只要搞出每个区间的进入位置和出去位置的和,就可以打标记了。

      1 /**************************************************************
      2     Problem: 4034
      3     User: idy002
      4     Language: C++
      5     Result: Accepted
      6     Time:2748 ms
      7     Memory:26616 kb
      8 ****************************************************************/
      9  
     10 #include <cstdio> 
     11 #include <cstdlib> 
     12 #define fprintf(...) 
     13 #define N 100010 
     14   
     15 typedef long long dnt; 
     16 struct Node { 
     17     dnt s, tag; 
     18     int tc[2]; 
     19     Node *ls, *rs; 
     20 }pool[N*6], *tail=pool, *root; 
     21   
     22 int n, m; 
     23 int head[N], dest[N+N], next[N+N], etot; 
     24 int in[N], out[N], type[N+N], ww[N], sww[N+N], idc; 
     25 bool vis[N]; 
     26   
     27 Node *build( int lf, int rg ) { 
     28     Node *nd = ++tail; 
     29     if( lf==rg ) { 
     30         nd->s = sww[lf]; 
     31         nd->tc[type[lf]]=1; 
     32         nd->tc[type[lf]^1]=0; 
     33         return nd; 
     34     } 
     35     int mid=(lf+rg)>>1; 
     36     nd->ls = build( lf, mid ); 
     37     nd->rs = build( mid+1, rg ); 
     38     nd->tc[0] = nd->ls->tc[0] + nd->rs->tc[0]; 
     39     nd->tc[1] = nd->ls->tc[1] + nd->rs->tc[1]; 
     40     nd->s = nd->ls->s + nd->rs->s; 
     41     fprintf( stderr, "[%d,%d] tc[0]=%d tc[1]=%d
    ", lf, rg, nd->tc[0], nd->tc[1] ); 
     42     return nd; 
     43 } 
     44 inline void pushdown( Node *nd ) { 
     45     if( nd->tag ) { 
     46         nd->ls->s += nd->ls->tc[0]*nd->tag - nd->ls->tc[1]*nd->tag; 
     47         nd->rs->s += nd->rs->tc[0]*nd->tag - nd->rs->tc[1]*nd->tag; 
     48         nd->ls->tag += nd->tag; 
     49         nd->rs->tag += nd->tag; 
     50         nd->tag = 0; 
     51     } 
     52 } 
     53 inline void update( Node *nd ) { 
     54     nd->s = nd->ls->s + nd->rs->s; 
     55 } 
     56 void modify( Node *nd, int lf, int rg, int L, int R, dnt delta ) { 
     57     if( L<=lf && rg<=R ) { 
     58         nd->s += nd->tc[0]*delta - nd->tc[1]*delta; 
     59         nd->tag += delta; 
     60         return; 
     61     } 
     62     int mid=(lf+rg)>>1; 
     63     pushdown(nd); 
     64     if( L<=mid ) modify( nd->ls, lf, mid, L, R, delta ); 
     65     if( R>mid ) modify( nd->rs, mid+1, rg, L, R, delta ); 
     66     update( nd ); 
     67 } 
     68 dnt query( Node *nd, int lf, int rg, int L, int R ) { 
     69     if( L<=lf && rg<=R ) { 
     70         fprintf( stderr, "( %d %d ) = %lld
    ", lf, rg, nd->s ); 
     71         return nd->s; 
     72     } 
     73     int mid=(lf+rg)>>1; 
     74     pushdown(nd); 
     75     dnt rt = 0; 
     76     if( L<=mid ) rt += query( nd->ls, lf, mid, L, R ); 
     77     if( R>mid ) rt += query( nd->rs, mid+1, rg, L, R ); 
     78     update(nd); 
     79     return rt; 
     80 } 
     81 void adde( int u, int v ) { 
     82     etot++; 
     83     next[etot] = head[u]; 
     84     dest[etot] = v; 
     85     head[u] = etot; 
     86 } 
     87 void dfs( int u, int fa ) { 
     88     if( vis[u] ) { 
     89         exit(0); 
     90         return; 
     91     } 
     92     vis[u] = true; 
     93     idc++; 
     94     in[u] = idc; 
     95     type[idc] = 0; 
     96     sww[idc] = ww[u]; 
     97     for( int t=head[u]; t; t=next[t] ) { 
     98         int v=dest[t]; 
     99         if( v==fa ) continue; 
    100         dfs(v,u); 
    101     } 
    102     idc++; 
    103     out[u] = idc; 
    104     type[idc] = 1; 
    105     sww[idc] = -ww[u]; 
    106 } 
    107 void mdf_sig( int u, int a ) { 
    108     modify( root, 1, idc, in[u], in[u], +a ); 
    109     modify( root, 1, idc, out[u], out[u], +a ); 
    110     fprintf( stderr, "modify( %d %d %d )
    ", in[u], in[u], +a ); 
    111     fprintf( stderr, "modify( %d %d %d )
    ", out[u], out[u], +a ); 
    112 } 
    113 void mdf_sub( int u, int a ) { 
    114     modify( root, 1, idc, in[u], out[u], +a ); 
    115     fprintf( stderr, "modify( %d %d %d )
    ", in[u], out[u], +a ); 
    116 } 
    117 dnt query( int u ) { 
    118     dnt rt = query( root, 1, idc, 1, in[u] ); 
    119     fprintf( stderr, "query( %d %d ) = %lld
    ", 1, in[u], rt ); 
    120     return rt; 
    121 } 
    122 int main() { 
    123     scanf( "%d%d", &n, &m ); 
    124     for( int i=1; i<=n; i++ ) 
    125         scanf( "%d", ww+i ); 
    126     for( int i=1,u,v; i<n; i++ ) { 
    127         scanf( "%d%d", &u, &v ); 
    128         adde( u, v ); 
    129         adde( v, u ); 
    130     } 
    131     fprintf( stderr, "dfs(...)
    " ); 
    132     dfs(1,1); 
    133     fprintf( stderr, "
    " ); 
    134     fprintf( stderr, "build(...)
    " ); 
    135     root = build( 1, idc ); 
    136     for( int t=0; t<m; t++ ) { 
    137         int opt, u, a; 
    138         scanf( "%d", &opt ); 
    139         fprintf( stderr, "%d
    ", opt ); 
    140         if( opt==1 ) { 
    141             scanf( "%d%d", &u, &a ); 
    142             mdf_sig( u, a ); 
    143         } else if( opt==2 ) { 
    144             scanf( "%d%d", &u, &a ); 
    145             mdf_sub( u, a ); 
    146         } else { 
    147             scanf( "%d", &u ); 
    148             printf( "%lld
    ", query(u) ); 
    149         } 
    150     } 
    151 } 
    152 
    View Code

    还有一种做法:链剖

    以前一直以为链剖只能用于链修改和链查询。。。。

    其实,链剖是一种特殊的DFS序,它合理地安排了DFS的顺序(先重儿子,再轻儿子),让我们可以把任意一条路径映射为O(logn)条连续的线段,然后就可以做很多问题了。

    其次是和子树相关的问题,我们一般是把DFS序弄出来,然后一个子树就是连续的一段,这样实现子树相关的操作。

    我们把两个结合起来就可以做到:链修改与查询+子树修改与查询。

    (好像还有一种链剖解决子树问题的方法,就是每个节点再记录所有轻边代表的子树的信息)。

      1 #include <cstdio> 
      2 #include <cstdlib> 
      3 #define fprintf(...) 
      4 #define N 100010 
      5  
      6 typedef long long dnt; 
      7 struct Node { 
      8     dnt s, tag; 
      9     int tc[2]; 
     10     Node *ls, *rs; 
     11 }pool[N*6], *tail=pool, *root; 
     12  
     13 int n, m; 
     14 int head[N], dest[N+N], next[N+N], etot; 
     15 int in[N], out[N], type[N+N], ww[N], sww[N+N], idc; 
     16 bool vis[N]; 
     17  
     18 Node *build( int lf, int rg ) { 
     19     Node *nd = ++tail; 
     20     if( lf==rg ) { 
     21         nd->s = sww[lf]; 
     22         nd->tc[type[lf]]=1; 
     23         nd->tc[type[lf]^1]=0; 
     24         return nd; 
     25     } 
     26     int mid=(lf+rg)>>1; 
     27     nd->ls = build( lf, mid ); 
     28     nd->rs = build( mid+1, rg ); 
     29     nd->tc[0] = nd->ls->tc[0] + nd->rs->tc[0]; 
     30     nd->tc[1] = nd->ls->tc[1] + nd->rs->tc[1]; 
     31     nd->s = nd->ls->s + nd->rs->s; 
     32     fprintf( stderr, "[%d,%d] tc[0]=%d tc[1]=%d
    ", lf, rg, nd->tc[0], nd->tc[1] ); 
     33     return nd; 
     34 } 
     35 inline void pushdown( Node *nd ) { 
     36     if( nd->tag ) { 
     37         nd->ls->s += nd->ls->tc[0]*nd->tag - nd->ls->tc[1]*nd->tag; 
     38         nd->rs->s += nd->rs->tc[0]*nd->tag - nd->rs->tc[1]*nd->tag; 
     39         nd->ls->tag += nd->tag; 
     40         nd->rs->tag += nd->tag; 
     41         nd->tag = 0; 
     42     } 
     43 } 
     44 inline void update( Node *nd ) { 
     45     nd->s = nd->ls->s + nd->rs->s; 
     46 } 
     47 void modify( Node *nd, int lf, int rg, int L, int R, dnt delta ) { 
     48     if( L<=lf && rg<=R ) { 
     49         nd->s += nd->tc[0]*delta - nd->tc[1]*delta; 
     50         nd->tag += delta; 
     51         return; 
     52     } 
     53     int mid=(lf+rg)>>1; 
     54     pushdown(nd); 
     55     if( L<=mid ) modify( nd->ls, lf, mid, L, R, delta ); 
     56     if( R>mid ) modify( nd->rs, mid+1, rg, L, R, delta ); 
     57     update( nd ); 
     58 } 
     59 dnt query( Node *nd, int lf, int rg, int L, int R ) { 
     60     if( L<=lf && rg<=R ) { 
     61         fprintf( stderr, "( %d %d ) = %lld
    ", lf, rg, nd->s ); 
     62         return nd->s; 
     63     } 
     64     int mid=(lf+rg)>>1; 
     65     pushdown(nd); 
     66     dnt rt = 0; 
     67     if( L<=mid ) rt += query( nd->ls, lf, mid, L, R ); 
     68     if( R>mid ) rt += query( nd->rs, mid+1, rg, L, R ); 
     69     update(nd); 
     70     return rt; 
     71 } 
     72 void adde( int u, int v ) { 
     73     etot++; 
     74     next[etot] = head[u]; 
     75     dest[etot] = v; 
     76     head[u] = etot; 
     77 } 
     78 void dfs( int u, int fa ) { 
     79     if( vis[u] ) { 
     80         exit(0); 
     81         return; 
     82     } 
     83     vis[u] = true; 
     84     idc++; 
     85     in[u] = idc; 
     86     type[idc] = 0; 
     87     sww[idc] = ww[u]; 
     88     for( int t=head[u]; t; t=next[t] ) { 
     89         int v=dest[t]; 
     90         if( v==fa ) continue; 
     91         dfs(v,u); 
     92     } 
     93     idc++; 
     94     out[u] = idc; 
     95     type[idc] = 1; 
     96     sww[idc] = -ww[u]; 
     97 } 
     98 void mdf_sig( int u, int a ) { 
     99     modify( root, 1, idc, in[u], in[u], +a ); 
    100     modify( root, 1, idc, out[u], out[u], +a ); 
    101     fprintf( stderr, "modify( %d %d %d )
    ", in[u], in[u], +a ); 
    102     fprintf( stderr, "modify( %d %d %d )
    ", out[u], out[u], +a ); 
    103 } 
    104 void mdf_sub( int u, int a ) { 
    105     modify( root, 1, idc, in[u], out[u], +a ); 
    106     fprintf( stderr, "modify( %d %d %d )
    ", in[u], out[u], +a ); 
    107 } 
    108 dnt query( int u ) { 
    109     dnt rt = query( root, 1, idc, 1, in[u] ); 
    110     fprintf( stderr, "query( %d %d ) = %lld
    ", 1, in[u], rt ); 
    111     return rt; 
    112 } 
    113 int main() { 
    114     scanf( "%d%d", &n, &m ); 
    115     for( int i=1; i<=n; i++ ) 
    116         scanf( "%d", ww+i ); 
    117     for( int i=1,u,v; i<n; i++ ) { 
    118         scanf( "%d%d", &u, &v ); 
    119         adde( u, v ); 
    120         adde( v, u ); 
    121     } 
    122     fprintf( stderr, "dfs(...)
    " ); 
    123     dfs(1,1); 
    124     fprintf( stderr, "
    " ); 
    125     fprintf( stderr, "build(...)
    " ); 
    126     root = build( 1, idc ); 
    127     for( int t=0; t<m; t++ ) { 
    128         int opt, u, a; 
    129         scanf( "%d", &opt ); 
    130         fprintf( stderr, "%d
    ", opt ); 
    131         if( opt==1 ) { 
    132             scanf( "%d%d", &u, &a ); 
    133             mdf_sig( u, a ); 
    134         } else if( opt==2 ) { 
    135             scanf( "%d%d", &u, &a ); 
    136             mdf_sub( u, a ); 
    137         } else { 
    138             scanf( "%d", &u ); 
    139             printf( "%lld
    ", query(u) ); 
    140         } 
    141     } 
    142 } 
    View Code
  • 相关阅读:
    Java 开源博客 Solo 2.5.0 发布
    redis集群部署及踩过的坑
    开源巨献:年度最佳 JavaScript 和 CSS 开源库推荐!
    Java9 新特性 详解
    eclipse 安装教程
    博客园代码高亮插件(类似csdn的代码插入)
    【超详细教程】使用Windows Live Writer 2012和Office Word 2013 发布文章到博客园全面总结
    软件测试学习视频 分享
    Oracle imp exp 导入导出 执行脚本
    在Ubuntu 15下搭建V/P/N服务器pptpd安装和配置
  • 原文地址:https://www.cnblogs.com/idy002/p/4469258.html
Copyright © 2011-2022 走看看