【HDU】5571 tree【动态点分治】
2016-11-01 11:14
316 查看
题目链接:【HDU】5571 tree【动态点分治】
题目大意:给一棵N节点的树,每个点有点权ai,有m次单点点权修改,每次修改以后,输出∑Ni=1∑Nj=1(aixoraj)⋅dis(ai,dj)的值。
题目分析:考虑每一位独立做,就是所有01对的对数*01对的距离,待修改可用动态树分治维护。每个重心树下每个节点保存所属的重心,所属的重心的哪个儿子的子树,到重心的距离。
压缩后代码:
题目大意:给一棵N节点的树,每个点有点权ai,有m次单点点权修改,每次修改以后,输出∑Ni=1∑Nj=1(aixoraj)⋅dis(ai,dj)的值。
题目分析:考虑每一位独立做,就是所有01对的对数*01对的距离,待修改可用动态树分治维护。每个重心树下每个节点保存所属的重心,所属的重心的哪个儿子的子树,到重心的距离。
#include <bits/stdc++.h> using namespace std ; typedef long long LL ; #define clr( a , x ) memset ( a , x , sizeof a ) const int MAXN = 30005 ; const int MAXE = 60005 ; struct Edge { int v , c , n ; Edge () {} Edge ( int v , int c , int n ) : v ( v ) , c ( c ) , n ( n ) {} } ; struct Node { int root , f , dep ; Node () {} Node ( int root , int f , int dep ) : root ( root ) , f ( f ) , dep ( dep ) {} } ; Edge E[MAXE] ; int H[MAXN] , cntE ; int Q[MAXN] , head , tail ; vector < Node > G[MAXN] ; int vis[MAXN] ; int dep[MAXN] ; int pre[MAXN] ; int siz[MAXN] ; int tree_cnt ; int pos[MAXN] ; int val[MAXN] ; LL dis[MAXN << 1][2] ; LL num[MAXN << 1][2] ; LL res[MAXN] ; int a[MAXN] ; int n , m ; void init () { cntE = 0 ; tree_cnt = 0 ; clr ( H , -1 ) ; clr ( vis , 0 ) ; } void addedge ( int u , int v , int c ) { E[cntE] = Edge ( v , c , H[u] ) ; H[u] = cntE ++ ; } int get_root ( int s ) { head = tail = 0 ; Q[tail ++] = s ; pre[s] = 0 ; while ( head != tail ) { int u = Q[head ++] ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( vis[v] || v == pre[u] ) continue ; pre[v] = u ; Q[tail ++] = v ; } } int root = s , root_siz = tail ; while ( head ) { int u = Q[-- head] , cnt = 0 ; siz[u] = 1 ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( vis[v] || v == pre[u] ) continue ; siz[u] += siz[v] ; if ( cnt < siz[v] ) cnt = siz[v] ; } cnt = max ( cnt , tail - siz[u] ) ; if ( cnt < root_siz ) { root_siz = cnt ; root = u ; } } return root ; } void calc ( int s , int d , int f , int root ) { head = tail = 0 ; dep[s] = d ; pre[s] = 0 ; Q[tail ++] = s ; while ( head != tail ) { int u = Q[head ++] ; G[u].push_back ( Node ( root , f , dep[u] ) ) ; for ( int i = H[u] ; ~i ; i = E[i].n ) { int v = E[i].v ; if ( vis[v] || v == pre[u] ) continue ; pre[v] = u ; dep[v] = dep[u] + E[i].c ; Q[tail ++] = v ; } } } void dfs ( int u ) { int root = get_root ( u ) ; vis[root] = 1 ; calc ( root , 0 , 1 , ++ tree_cnt ) ; for ( int i = H[root] ; ~i ; i = E[i].n ) { if ( !vis[E[i].v] ) calc ( E[i].v , E[i].c , -1 , ++ tree_cnt ) ; } for ( int i = H[root] ; ~i ; i = E[i].n ) { if ( !vis[E[i].v] ) dfs ( E[i].v ) ; } vis[root] = 0 ; } void solve () { int u , v , c ; init () ; for ( int i = 1 ; i <= n ; ++ i ) { scanf ( "%d" , &a[i] ) ; a[i] <<= 1 ; G[i].clear () ; } for ( int i = 1 ; i < n ; ++ i ) { scanf ( "%d%d%d" , &u , &v , &c ) ; addedge ( u , v , c ) ; addedge ( v , u , c ) ; } scanf ( "%d" , &m ) ; for ( int i = 1 ; i <= m ; ++ i ) { scanf ( "%d%d" , &pos[i] , &val[i] ) ; val[i] <<= 1 ; res[i] = 0 ; } dfs ( 1 ) ; for ( int o = 0 ; o < 14 ; ++ o ) { for ( int i = 1 ; i <= tree_cnt ; ++ i ) { dis[i][0] = dis[i][1] = 0 ; num[i][0] = num[i][1] = 0 ; } LL ans = 0 ; for ( int i = 1 ; i <= n ; ++ i ) { int v = ( a[i] >>= 1 ) & 1 ; for ( int j = 0 ; j < G[i].size () ; ++ j ) { Node x = G[i][j] ; ans += x.f * ( x.dep * num[x.root][v ^ 1] + dis[x.root][v ^ 1] ) ; dis[x.root][v] += x.dep ; num[x.root][v] ++ ; } } for ( int i = 1 ; i <= m ; ++ i ) { int v1 = a[pos[i]] & 1 ; int v2 = ( val[i] >>= 1 ) & 1 ; if( v1 != v2 ) { for ( int j = 0 ; j < G[pos[i]].size () ; ++ j ) { Node x = G[pos[i]][j] ; ans -= x.f * ( x.dep * num[x.root][v1 ^ 1] + dis[x.root][v1 ^ 1] ) ; dis[x.root][v1] -= x.dep ; num[x.root][v1] -- ; ans += x.f * ( x.dep * num[x.root][v2 ^ 1] + dis[x.root][v2 ^ 1] ) ; dis[x.root][v2] += x.dep ; num[x.root][v2] ++ ; } a[pos[i]] ^= v1 ^ v2 ; } res[i] += ans * ( 1 << o ) ; } } for ( int i = 1 ; i <= m ; ++ i ) { printf ( "%lld\n" , res[i] ) ; } } int main () { while ( ~scanf ( "%d" , &n ) ) solve () ; return 0 ; }
压缩后代码:
#include <bits/stdc++.h> using namespace std; typedef long long LL; #define clr(a,x) memset(a,x,sizeof a) const int MAXN=30005; const int MAXE=60005; struct Edge{ int v,c,n; Edge(){} Edge(int v,int c,int n):v(v),c(c),n(n){} }; struct Node{ int rt,f,dep; Node(){} Node(int rt,int f,int dep):rt(rt),f(f),dep(dep){} }; Edge E[MAXE]; int H[MAXN],cntE; int Q[MAXN],head,tail; vector<Node>G[MAXN]; int vis[MAXN],dep[MAXN],pre[MAXN],siz[MAXN],cnt[MAXN],pos[MAXN],val[MAXN],tcnt; LL dis[MAXN<<1][2],num[MAXN<<1][2],res[MAXN]; int a[MAXN],n,m; void init(){ cntE=tcnt=0; clr(H,-1),clr(vis,0); } void addedge(int u,int v,int c){ E[cntE]=Edge(v,c,H[u]); H[u]=cntE++; } int get_rt(int s){ int u,v,i,rt=s,l=0,r=0; for(l=pre[Q[0]=s]=0,r=1;l!=r;){ for(v=E[i=H[u=Q[l++]]].v;~i;v=E[i=E[i].n].v)if(!vis[v]&&v!=pre[u]){ pre[Q[r++]=v]=u; siz[v]=1,cnt[v]=0; } } for(int sz=r,u=Q[l-1];l--;u=Q[l-1]){ siz[pre[u]]+=siz[u]; if(cnt[pre[u]]<siz[u])cnt[pre[u]]=siz[u]; cnt[u]=max(cnt[u],r-siz[u]); if(cnt[u]<sz)sz=cnt[u],rt=u; } return rt; } void calc(int s,int d,int f,int rt){ int l,r,u,v,i; for(l=r=pre[s]=0,dep[Q[r++]=s]=d;l!=r;){ G[Q[l]].push_back(Node(rt,f,dep[Q[l]])); for(v=E[i=H[u=Q[l++]]].v;~i;v=E[i=E[i].n].v){ if(!vis[v]&&v!=pre[u])dep[v]=dep[pre[Q[r++]=v]=u]+E[i].c; } } } void dfs(int u){ int rt=get_rt(u); vis[rt]=1; calc(rt,0,1,++tcnt); for(int i=H[rt];~i;i=E[i].n)if(!vis[E[i].v])calc(E[i].v,E[i].c,-1,++tcnt); for(int i=H[rt];~i;i=E[i].n)if(!vis[E[i].v])dfs(E[i].v); vis[rt]=0; } void solve(){ int u,v,c; init(); for(int i=1;i<=n;G[i].clear(),a[i]<<=1,++i)scanf("%d",&a[i]); for(int i=1;i<n;++i){ scanf("%d%d%d",&u,&v,&c); addedge(u,v,c); addedge(v,u,c); } scanf("%d",&m); for(int i=1;i<=m;val[i]<<=1,res[i]=0,++i)scanf("%d%d",&pos[i],&val[i]); dfs(1); for(int o=0;o<14;++o){ for(int i=1;i<=tcnt;++i){ dis[i][0]=dis[i][1]=0; num[i][0]=num[i][1]=0; } LL ans=0; for(int i=1;i<=n;++i){ int v=(a[i]>>=1)&1; for(int j=0;j<G[i].size();++j){ Node x=G[i][j]; ans+=x.f*(x.dep*num[x.rt][v^1]+dis[x.rt][v^1]); dis[x.rt][v]+=x.dep; num[x.rt][v]++; } } for(int i=1;i<=m;++i){ int v1=a[pos[i]]&1; int v2=(val[i]>>=1)&1; if(v1!=v2){ for(int j=0;j<G[pos[i]].size();++j){ Node x=G[pos[i]][j]; ans-=x.f*(x.dep*num[x.rt][v1^1]+dis[x.rt][v1^1]); dis[x.rt][v1]-=x.dep; num[x.rt][v1]--; ans+=x.f*(x.dep*num[x.rt][v2^1]+dis[x.rt][v2^1]); dis[x.rt][v2]+=x.dep; num[x.rt][v2]++; } a[pos[i]]^=v1^v2; } res[i]+=ans*(1<<o); } } for(int i=1;i<=m;++i){ printf("%lld\n",res[i]); } } int main(){ while(~scanf("%d",&n))solve(); return 0; }
相关文章推荐
- hdu 5571 tree (动态点分治)
- HDU 4718 The LCIS on the Tree (动态树LCT)
- 【HDU】4812 D Tree 点分治
- HDU 4670 Cube number on a tree ( 树的点分治 )
- Hdu 5401 Persistent Link/cut Tree 树上分治/记忆化搜索
- HDU 6065 RXD, tree and sequence(在线倍增LCA+CDQ分治+离线tarjan-LCA+dp)
- HDU 3924 Extend-Tree 【一道不错的分治题目】
- HDU - 5002 Tree (动态树模板)
- SPOJ QTREE Query on a tree V ——动态点分治
- SPOJ QTREE4 Query on a tree IV ——动态点分治
- hdu 6183 Color it(动态线段树,cdq分治)
- hdu 4670 Cube number on a tree(点分治)
- hdu 5398 GCD Tree 2015多校联合训练赛#9 LCT,动态生成树
- 【HDU】5314 Happy King【动态树(点分治)】
- HDU D Tree [点分治]
- hdu 4670 Cube number on a tree(点分治)
- HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)
- 【HDU】5267 pog loves szh IV【动态点分治】
- 【树的分治】 HDU 4670 Cube number on a tree
- hdu 6191 Query on A Tree(字典树启发式合并(动态建树) 可持久化字典树+dfs序)