# bzoj 4034

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\n", 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\n", 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 )\n", in[u], in[u], +a );
111     fprintf( stderr, "modify( %d %d %d )\n", 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 )\n", 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\n", 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(...)\n" );
132     dfs(1,1);
133     fprintf( stderr, "\n" );
134     fprintf( stderr, "build(...)\n" );
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\n", 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\n", query(u) );
149         }
150     }
151 }
152 
View Code

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

  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\n", 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\n", 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 )\n", in[u], in[u], +a );
102     fprintf( stderr, "modify( %d %d %d )\n", 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 )\n", 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\n", 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(...)\n" );
123     dfs(1,1);
124     fprintf( stderr, "\n" );
125     fprintf( stderr, "build(...)\n" );
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\n", 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\n", query(u) );
140         }
141     }
142 } 
View Code

posted @ 2015-04-30 16:33  idy002  阅读(238)  评论(0编辑  收藏  举报