bzoj 3052 树上莫队 待修改
感谢:
http://vfleaking.blog.163.com/blog/static/174807634201311011201627/
http://hzwer.com/5250.html
好吧,收获两点:
1、带修改,其实就是暴力,只是将同一块的查询再按照时间顺序排,这样就能减少在修改操作上“爬"的时间,其实就是利用了数据随机这个特点,可以构造数据来卡。
2、以前排序的方法是u按照块,v按照dfs序,这次两个都是按照块,其实差不多。
1 /************************************************************** 2 Problem: 3052 3 User: idy002 4 Language: C++ 5 Result: Accepted 6 Time:101223 ms 7 Memory:21792 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <cmath> 12 #include <vector> 13 #include <algorithm> 14 #define P(p) ((1)<<(p)) 15 #define maxn 100010 16 #define maxp 16 17 using namespace std; 18 19 typedef long long dint; 20 21 int n, m, q, qq, qm; 22 int cc[maxn], ww[maxn], vv[maxn]; 23 vector<int> g[maxn], stk; 24 int mno[maxn], mcc_siz, mcc_cnt; 25 int anc[maxn][maxp+1], depth[maxn], dfn[maxn], dfs_clock; 26 bool stat[maxn]; 27 dint cnt[maxn], cur_ans; 28 dint ans[maxn]; 29 int mdu[maxn], mdc[maxn], mdo[maxn], mdcc[maxn]; 30 31 struct Qu { 32 int u, v, t, id; 33 bool operator<( const Qu & b ) const { 34 if( mno[u]^mno[b.u] ) return mno[u]<mno[b.u]; 35 if( mno[v]^mno[b.v] ) return mno[v]<mno[b.v]; 36 return t<b.t; 37 } 38 }; 39 Qu qu[maxn]; 40 41 int dfs( int u ) { 42 dfn[u] = ++dfs_clock; 43 depth[u] = depth[anc[u][0]]+1; 44 for( int p=1; p<=maxp; p++ ) { 45 anc[u][p] = anc[anc[u][p-1]][p-1]; 46 if( !anc[u][p] ) break; 47 } 48 49 int sz = 0; 50 for( int t=0; t<g[u].size(); t++ ) { 51 int v = g[u][t]; 52 if( v==anc[u][0] ) continue; 53 anc[v][0] = u; 54 sz += dfs(v); 55 if( sz > mcc_siz ) { 56 mcc_cnt++; 57 for( int i=1; i<=sz; i++ ) { 58 mno[stk.back()] = mcc_cnt; 59 stk.pop_back(); 60 } 61 sz = 0; 62 } 63 } 64 stk.push_back( u ); 65 return sz+1; 66 } 67 68 int lca( int u, int v ) { 69 if( depth[u]<depth[v] ) swap(u,v); 70 int t = depth[u]-depth[v]; 71 for( int p=0; t; t>>=1, p++ ) 72 if( t&1 ) u=anc[u][p]; 73 if( u==v ) return u; 74 for( int p=maxp; p>=0 && anc[u][0]!=anc[v][0]; p-- ) 75 if( anc[u][p]!=anc[v][p] ) 76 u = anc[u][p], v = anc[v][p]; 77 return anc[u][0]; 78 } 79 80 void inv_sig( int u ) { 81 if( stat[u] ) { 82 cur_ans -= (dint)ww[cnt[cc[u]]]*vv[cc[u]]; 83 cnt[cc[u]]--; 84 } else { 85 cnt[cc[u]]++; 86 cur_ans += (dint)ww[cnt[cc[u]]]*vv[cc[u]]; 87 } 88 stat[u] ^= 1; 89 } 90 91 void chg_sig( int u, int type ) { 92 if( stat[u] ) { 93 inv_sig(u); 94 cc[u] = type; 95 inv_sig(u); 96 } else cc[u] = type; 97 } 98 99 void inv_chain( int u, int v ) { 100 int ca = lca(u,v); 101 for( ; u!=ca; u=anc[u][0] ) inv_sig(u); 102 for( ; v!=ca; v=anc[v][0] ) inv_sig(v); 103 } 104 void app_time( int fm, int to ) { 105 while( fm<to ) { 106 fm++; 107 chg_sig(mdu[fm],mdc[fm]); 108 } 109 while( to<fm ) { 110 chg_sig(mdu[fm],mdo[fm]); 111 fm--; 112 } 113 } 114 115 void work() { 116 sort( qu+1, qu+1+qq ); 117 int ou=qu[1].u; 118 int ov=qu[1].u; 119 int ot=0; 120 for( int i=1; i<=qq; i++ ) { 121 int u = qu[i].u, v = qu[i].v; 122 inv_chain( u, ou ); 123 inv_chain( v, ov ); 124 app_time( ot, qu[i].t ); 125 ot = qu[i].t; 126 ou = u; 127 ov = v; 128 int ca = lca(u,v); 129 inv_sig( ca ); 130 ans[qu[i].id] = cur_ans; 131 inv_sig( ca ); 132 } 133 } 134 135 int main() { 136 scanf( "%d%d%d", &n, &m, &q ); 137 for( int i=1; i<=m; i++ ) scanf( "%d", vv+i ); 138 for( int i=1; i<=n; i++ ) scanf( "%d", ww+i ); 139 for( int i=1,u,v; i<n; i++ ) { 140 scanf( "%d%d", &u, &v ); 141 g[u].push_back(v); 142 g[v].push_back(u); 143 } 144 mcc_siz = (int)(pow(n,2.0/3.0))+1; 145 dfs(1); 146 while( !stk.empty() ) { 147 mno[stk.back()] = mcc_cnt; 148 stk.pop_back(); 149 } 150 for( int i=1; i<=n; i++ ) { 151 scanf( "%d", cc+i ); 152 mdcc[i] = cc[i]; 153 } 154 for( int i=1,type,x,y; i<=q; i++ ) { 155 scanf( "%d%d%d", &type, &x, &y ); 156 if( !type ) { 157 qm++; 158 mdu[qm]=x, mdc[qm]=y, mdo[qm]=mdcc[x]; 159 mdcc[x] = y; 160 } else { 161 qq++; 162 qu[qq].u=x, qu[qq].v=y, qu[qq].t=qm, qu[qq].id=qq; 163 } 164 } 165 work(); 166 for( int i=1; i<=qq; i++ ) 167 printf( "%lld\n", ans[i] ); 168 }