zoukankan      html  css  js  c++  java
  • [HZOI 2015]树黑白

    【题目描述】

    给定一棵树,要求维护以下操作:

    1、M u 将u节点反色

    2、Q u 查询u到所有黑色节点距离和

    【输入格式】

    第一行n,m 表示节点总数和操作次数

    之后n-1行,每行u,v表示两个端点,w表示边权

    之后m行,操作如题意

    n,m<=200000,边权<=1000

    一开始所有点均为白色

    【输出格式】

    输出每次Q的答案

    【样例输入】

    7 5

    2 1 144

    3 2 361

    4 3 236

    5 3 697

    6 2 140

    7 5 718

    Q 4

    M 4

    Q 5

    Q 1

    Q 7

    【样例输出】

    0

    933

    741

    1651

    题解:

    和上一题差不多,多了一个修改操作。

    还是动态点分,每个节点储存两个数,分别表示整棵子树到根和到根节点的父节点的距离和。

    容斥一下就好。

      1 //Never forget why you start
      2 #include<iostream>
      3 #include<cstdio>
      4 #include<cstdlib>
      5 #include<cstring>
      6 #include<cmath>
      7 #include<algorithm>
      8 #define inf (2147483647)
      9 using namespace std;
     10 int n,m,a[200005],lim;
     11 struct node{
     12   int next,to,dis;
     13 }edge[400005];
     14 int head[200005],size;
     15 void putin(int from,int to,int dis){
     16   size++;
     17   edge[size].next=head[from];
     18   edge[size].to=to;
     19   edge[size].dis=dis;
     20   head[from]=size;
     21 }
     22 int fa[200005][20],dis[200005],depth[200005];
     23 void dfs1(int r,int father){
     24   int i;
     25   fa[r][0]=father;
     26   depth[r]=depth[father]+1;
     27   for(i=head[r];i!=-1;i=edge[i].next){
     28     int y=edge[i].to;
     29     if(y!=father){
     30       dis[y]=dis[r]+edge[i].dis;
     31       dfs1(y,r);
     32     }
     33   }
     34 }
     35 void make(){
     36   lim=log(n)/log(2);
     37   for(int i=1;i<=lim;i++)
     38     for(int j=1;j<=n;j++)
     39       fa[j][i]=fa[fa[j][i-1]][i-1];
     40 }
     41 int LCA(int x,int y){
     42   if(depth[x]<depth[y])swap(x,y);
     43   for(int i=lim;i>=0;i--)
     44     if(depth[fa[x][i]]>=depth[y])
     45       x=fa[x][i];
     46   if(x!=y){
     47     for(int i=lim;i>=0;i--)
     48       if(fa[x][i]!=fa[y][i])
     49     x=fa[x][i],y=fa[y][i];
     50     x=fa[x][0];
     51     y=fa[y][0];
     52   }
     53   return x;
     54 }
     55 int dist(int x,int y){
     56   int lca=LCA(x,y);
     57   return dis[x]+dis[y]-dis[lca]*2;
     58 }
     59 int tot,root,vis[200005],d[200005],ff[200005],cnt[200005];
     60 void getroot(int r,int father){
     61   int i;
     62   cnt[r]=1;d[r]=0;
     63   for(i=head[r];i!=-1;i=edge[i].next){
     64     int y=edge[i].to;
     65     if(y!=father&&!vis[y]){
     66       getroot(y,r);
     67       cnt[r]+=cnt[y];
     68       d[r]=max(d[r],cnt[y]);
     69     }
     70   }
     71   d[r]=max(d[r],tot-cnt[r]);
     72   if(d[root]>d[r])root=r;
     73 }
     74 void buildtree(int r,int father){
     75   int i,all=tot;
     76   ff[r]=father;vis[r]=1;
     77   for(i=head[r];i!=-1;i=edge[i].next){
     78     int y=edge[i].to;
     79     if(!vis[y]){
     80       if(cnt[y]>cnt[r])cnt[y]=all-cnt[r];tot=cnt[y];
     81       root=0;getroot(y,r);buildtree(root,r);
     82     }
     83   }
     84 }
     85 int p[200005][2];
     86 void insert(int x,int v){
     87   int i;
     88   for(i=x;ff[i];i=ff[i]){
     89     int len=dist(x,ff[i]);
     90     p[i][1]+=len*v;
     91     p[ff[i]][0]+=len*v;
     92   }
     93   for(i=x;i;i=ff[i])cnt[i]+=v;
     94 }
     95 int find(int x){
     96   int i,ans=p[x][0];
     97   for(i=x;ff[i];i=ff[i]){
     98     int len=dist(x,ff[i]);
     99     ans+=p[ff[i]][0];
    100     ans-=p[i][1];
    101     ans+=(cnt[ff[i]]-cnt[i])*len;
    102   }
    103   return ans;
    104 }
    105 void clean(){
    106   memset(head,-1,sizeof(head));
    107   size=0;
    108 }
    109 int main(){
    110   freopen("A_Tree.in","r",stdin);
    111   freopen("A_Tree.out","w",stdout);
    112   int i,j;
    113   clean();
    114   scanf("%d%d",&n,&m);
    115   for(i=1;i<n;i++){
    116     int u,v,l;
    117     scanf("%d%d%d",&u,&v,&l);
    118     putin(u,v,l);
    119     putin(v,u,l);
    120   }
    121   dfs1(1,0);make();
    122   tot=n;root=0;d[0]=inf;
    123   getroot(1,0);buildtree(root,0);
    124   for(i=1;i<=n;i++)if(!ff[i]){root=i;break;}
    125   char s[10];
    126   memset(cnt,0,sizeof(cnt));
    127   while(m--){
    128     scanf("%s",s);
    129     if(s[0]=='Q'){
    130       int x;
    131       scanf("%d",&x);
    132       printf("%d
    ",find(x));
    133     }
    134     else{
    135       int x;
    136       scanf("%d",&x);
    137       a[x]^=1;
    138       if(a[x])insert(x,1);
    139       else insert(x,-1);
    140     }
    141   }
    142   return 0;
    143 }
  • 相关阅读:
    UVa 1354 天平难题 (枚举二叉树)
    广西邀请赛总结
    UVa 12118 检查员的难题 (dfs判连通, 构造欧拉通路)
    UVA
    Uva 127 "Accordian" Patience (模拟)
    UVA 10539 Almost Prime Numbers( 素数因子)
    HDU 1272 小希的迷宫(并查集)
    HDU 1213 How Many Tables (并查集)
    POJ 2236 Wireless Network(并查集)
    HDU 1233 还是畅通工程 ( Kruskal或Prim)
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8327429.html
Copyright © 2011-2022 走看看