• [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 }
  • 相关阅读:
    0817JavaScript--------------循环语句
    MySQL数据库的几种引擎
    spring-boot+mybatisPlus+shiro的集成demo 我用了5天
    Nginx 自定义404、500、502 页面
    论Photoshop的正确安装姿势
    记定位一次多线程数据安全问题
    记服务器被黑客攻击事件(肉鸡)
    Spring-Boot 使用 Jedis 操作 Redis
    JavaScript 中 replace方法 替换所有字符串
    关于图文转换的web工具
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8327429.html
Copyright © 2020-2023  润新知