zoukankan      html  css  js  c++  java
  • 【CH#56C】异象石

    这是一道毒瘤的LCA的题目。

    我们对这棵树进行一次dfs,求出每一个点的时间戳,不难发现,我们按照时间戳排序,把异象石的节点排序,并且累加相邻两点的路径,最后的结果就是所求答案的两倍。

    因此,我们采用STL中的set,按照时间戳递增的顺序维护异象石出现的序列,并用变量ans记录相邻两点的距离之和,那么答案就是ans/2.

    设path(x,y)表示x,y之间的距离,d[x]表示x在树中的深度,那么存在path(x,y)=d[x]+d[y]-2*d[lca(x,y)],d数组可以通过dfs或bfs求出,lca可以通过倍增实现。

    如果某一节点出现了异象石,那么我们根据这个节点的时间戳,把他放到set中的合适位置,假设他的节点为x,在set中左边/右边的节点分别是l,r,那么ans+=path(l,x)+path(x,r)-path(l,r),对于某一点异象石消失,那么操作类似,对于每次询问,我们输出ans即可。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <algorithm>
      5 #include <queue>
      6 #include <set>
      7 #include <cmath>
      8 using namespace std;
      9 typedef long long ll;
     10 typedef set<int>::iterator It;
     11 It it;
     12 struct node {
     13     int next,to,dis;
     14 }a[100010<<1];
     15 int head[100010<<1],num,vis[100010],tot,n,m,fvis[100010],d[100010],f[100010][23];
     16 ll ans,dis[100010][23];
     17 queue<int> q;
     18 set<int> s;
     19 char c[2];
     20 inline void add(int from,int to,int dis) {
     21     a[++num].next=head[from]; a[num].to=to; a[num].dis=dis; head[from]=num;
     22 }
     23 void bfs() {
     24     vis[1]=1;
     25     d[1]=1;
     26     q.push(1);
     27     while(q.size()) {
     28         int now=q.front();
     29         q.pop();
     30         for(int i=head[now];i;i=a[i].next) {
     31             int v=a[i].to;
     32             if(vis[v]) continue ;
     33             q.push(v); vis[v]=1; d[v]=d[now]+1;
     34             dis[v][0]=a[i].dis;
     35             f[v][0]=now;
     36             for(int j=1;j<=20;j++) {
     37                 f[v][j]=f[f[v][j-1]][j-1];
     38                 dis[v][j]=dis[v][j-1]+dis[f[v][j-1]][j-1];
     39             }
     40         }
     41     }
     42 }
     43 void dfs(int now) {
     44     vis[now]=++tot;
     45     fvis[tot]=now;
     46     for(int i=head[now];i;i=a[i].next)
     47         if(!vis[a[i].to]) dfs(a[i].to);
     48 }
     49 ll lca(int x,int y) {
     50     ll ret=0;
     51     if(d[x]>d[y]) swap(x,y);
     52     for(int i=20;i>=0;i--)
     53         if(d[f[y][i]]>=d[x]) {
     54             ret+=dis[y][i];
     55             y=f[y][i];
     56         } 
     57     if(x==y) return ret;
     58     for(int i=20;i>=0;i--)
     59         if(f[x][i]!=f[y][i]) {
     60             ret+=dis[x][i]+dis[y][i];
     61             x=f[x][i];
     62             y=f[y][i];
     63         }
     64     return ret+dis[x][0]+dis[y][0];
     65 }
     66 inline It turnl(It it) {
     67     if(it==s.begin()) return --s.end();
     68     return --it;
     69 }
     70 inline It turnr(It it) {
     71     if(it==--s.end()) return s.begin();
     72     return ++it;
     73 }
     74 int main() {
     75     scanf("%d",&n);
     76     for(int i=1,x,y,z;i<n;i++) {
     77         scanf("%d%d%d",&x,&y,&z);
     78         add(x,y,z);
     79         add(y,x,z);
     80     }
     81     bfs();
     82     memset(vis,0,sizeof(vis)); tot=0;
     83     dfs(1);
     84     scanf("%d",&m);
     85     while(m--) {
     86         scanf("%s",c);
     87         if(c[0]=='+') {
     88             int x;
     89             scanf("%d",&x);
     90             if(s.size()) {
     91                 it=s.lower_bound(vis[x]);
     92                 if(it==s.end()) it=s.begin();
     93                 int y=*turnl(it);
     94                 ans+=lca(x,fvis[y])+lca(x,fvis[*it])-lca(fvis[y],fvis[*it]);
     95             }
     96             s.insert(vis[x]);
     97         }
     98         else if(c[0]=='-') {
     99             int x;
    100             scanf("%d",&x);
    101             it=s.find(vis[x]);
    102             int y=*turnl(it);
    103             it=turnr(it);
    104             ans-=lca(x,fvis[y])+lca(x,fvis[*it])-lca(fvis[y],fvis[*it]);
    105             s.erase(vis[x]);
    106         }
    107         else if(c[0]=='?') printf("%lld
    ",ans/2);
    108     }
    109     return 0;
    110 }
    AC Code
  • 相关阅读:
    kali禁止自动挂载U盘(gnome)
    Kali开启远程桌面服务(gnome桌面环境)
    KVM安装Win7时USB3.0无法使用的坑
    Linux上VLAN的创建
    小程序 局部页面 自定义滚动条
    两个图层一上一下div view
    js 数组去重
    css > 的写法 html
    块级元素和行内元素
    小程序 css 文字溢出,长度过长用 。。。
  • 原文地址:https://www.cnblogs.com/shl-blog/p/10802161.html
Copyright © 2011-2022 走看看