您的位置:首页 > 其它

【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对的距离,待修改可用动态树分治维护。每个重心树下每个节点保存所属的重心,所属的重心的哪个儿子的子树,到重心的距离。

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: