zoukankan      html  css  js  c++  java
  • [bzoj3786] 星系探索

    这道题搞了好几天......当然不是一直在搞,中间考了场试,改了改考试题......

    这题先写的东西觉得思路太混乱,翻了翻题解之后思路清晰了一些,重构了。

    题目传送门

    这道题思路很清楚:用splay维护入栈出栈序。

    对于子树修改的操作,splay之后,打标记。

    对于换根的操作,splay之后把整个子树拿下来,再splay,最后再接到上面。

    在入栈出栈序的体现就是区间的平移:1 2 3 3 2 4 4 1 --> 1 2 2 4 3 3 4 1 (此为把3的根从2换成4)。

    查询操作就是查询入栈出栈序上,in[p]的前缀和。

    具体写的话就比较复杂了,码量比较大。

    解释代码里几个名称:

    empty就是指空位置,由于0有用,所以不能用0作为空位置。

    我们可以让没用到的n*2+2作为空位置的标志。

    in,out入栈出栈。

    fl标记是正是负,入栈处为正,出栈处为负。

    sz不是指splay中的子树大小,而是子树中fl的和。

    v指节点值,sum指splay中子树的v的和。

    lz为懒惰标记。

    注意要开long long。

      1 #include<cstdio>
      2 #define empty 2*n+2
      3 #define ll long long
      4 #define id(x) (s[f[x]][1]==x)
      5 
      6 int n,m;
      7 int hd[100005],nx[200010],to[200010],ec;
      8 int in[100005],out[100005],iv[100005];
      9 int s[200010][2],f[200010],root;
     10 ll v[200010],sum[200010],lz[200010];
     11 int fl[200010],sz[200010];
     12 int dc;
     13 
     14 void dfs(int p)
     15 {
     16     in[p]=++dc;
     17     v[dc]=sum[dc]=iv[p];
     18     sz[dc]=fl[dc]=1;
     19     for(int i=hd[p];i;i=nx[i])dfs(to[i]);
     20     out[p]=++dc;
     21     v[dc]=sum[dc]=-iv[p];
     22     sz[dc]=fl[dc]=-1;
     23 }
     24 
     25 void pushup(int p)
     26 {
     27     sum[p]=sum[s[p][0]]+sum[s[p][1]]+v[p];
     28     sz[p]=sz[s[p][0]]+sz[s[p][1]]+fl[p];
     29 }
     30 
     31 int build(int l,int r)
     32 {
     33     if(l>r)return empty;
     34     int mid=(l+r)>>1;
     35     s[mid][0]=build(l,mid-1);
     36     s[mid][1]=build(mid+1,r);
     37     if(s[mid][0]!=empty)f[s[mid][0]]=mid;
     38     if(s[mid][1]!=empty)f[s[mid][1]]=mid;
     39     pushup(mid);
     40     return mid;
     41 }
     42 
     43 void pushdown(int p)
     44 {
     45     if(!lz[p])return;
     46     if(s[p][0]!=empty)
     47     {
     48         sum[s[p][0]]+=sz[s[p][0]]*lz[p];
     49         v[s[p][0]]+=fl[s[p][0]]*lz[p];
     50         lz[s[p][0]]+=lz[p];
     51     }
     52     if(s[p][1]!=empty)
     53     {
     54         sum[s[p][1]]+=sz[s[p][1]]*lz[p];
     55         v[s[p][1]]+=fl[s[p][1]]*lz[p];
     56         lz[s[p][1]]+=lz[p];
     57     }
     58     lz[p]=0;
     59 }
     60 
     61 void rotate(int p)
     62 {
     63     int fa=f[p];
     64     int k=id(p);
     65     s[fa][k]=s[p][!k];
     66     s[p][!k]=fa;
     67     s[f[fa]][id(fa)]=p;
     68     f[p]=f[fa];
     69     f[s[fa][k]]=fa;
     70     f[fa]=p;
     71     pushup(fa);
     72     pushup(p);
     73 }
     74 
     75 void update(int p)
     76 {
     77     if(p!=root)update(f[p]);
     78     pushdown(p);
     79 }
     80 
     81 void splay(int p,int g)
     82 {
     83     update(p);
     84     while(f[p]!=g)
     85     {
     86         int fa=f[p];
     87         if(f[fa]==g)
     88         {
     89             rotate(p);
     90             break;
     91         }
     92         if(id(p)^id(fa))rotate(p);
     93         else rotate(fa);
     94         rotate(p);
     95     }
     96     if(g==empty)root=p;
     97 }
     98 
     99 int pre(int p)
    100 {
    101     if(s[p][0]!=empty)
    102     {
    103         for(p=s[p][0];s[p][1]!=empty;p=s[p][1]);
    104         return p;
    105     }
    106     while(id(p)==0)p=f[p];
    107     return f[p];
    108 }
    109 
    110 int post(int p)
    111 {
    112     if(s[p][1]!=empty)
    113     {
    114         for(p=s[p][1];s[p][0]!=empty;p=s[p][0]);
    115         return p;
    116     }
    117     while(id(p)==1)p=f[p];
    118     return f[p];
    119 }
    120 
    121 void quary()
    122 {
    123     int x;
    124     scanf("%d",&x);
    125     splay(post(in[x]),empty);
    126     printf("%lld
    ",sum[s[root][0]]);    
    127 }
    128 
    129 void change()
    130 {
    131     int x,y;
    132     scanf("%d%d",&x,&y);
    133     splay(pre(in[x]),empty);
    134     splay(post(out[x]),root);
    135     int tar=s[root][1];
    136     int tmp=s[tar][0];
    137     s[tar][0]=empty;
    138     f[tmp]=empty;
    139     sz[tar]-=sz[tmp];
    140     sum[tar]-=sum[tmp];
    141     sz[root]-=sz[tmp];
    142     sum[root]-=sum[tmp];
    143     splay(in[y],empty);
    144     splay(post(in[y]),root);
    145     tar=s[root][1];
    146     s[tar][0]=tmp;
    147     f[tmp]=tar;
    148     pushup(tar);
    149     pushup(root);
    150 }
    151 
    152 void flux()
    153 {
    154     int x,y;
    155     scanf("%d%d",&x,&y);
    156     splay(pre(in[x]),empty);
    157     splay(post(out[x]),root);
    158     int tar=s[s[root][1]][0];
    159     lz[tar]+=y;
    160     sum[tar]+=sz[tar]*y;
    161     v[tar]+=fl[tar]*y;
    162     tar=f[tar];
    163     pushup(tar);
    164     pushup(root);
    165 }
    166 
    167 int main()
    168 {
    169     scanf("%d",&n);
    170     for(int i=2;i<=n;i++)
    171     {
    172         int t;
    173         scanf("%d",&t);
    174         to[++ec]=i;
    175         nx[ec]=hd[t];
    176         hd[t]=ec;
    177     }
    178     for(int i=1;i<=n;i++)scanf("%d",&iv[i]);
    179     for(int i=0;i<=2*n+1;i++)f[i]=s[i][0]=s[i][1]=empty;
    180     dfs(1);
    181     root=build(0,2*n+1);
    182     scanf("%d",&m);
    183     while(m--)
    184     {
    185         char op[5];
    186         scanf("%s",op+1);
    187         if(op[1]=='Q')quary();
    188         if(op[1]=='C')change();
    189         if(op[1]=='F')flux();
    190     }
    191     return 0;
    192 }
    bzoj 3786
  • 相关阅读:
    规矩与管理
    信息系统叫设施比叫工具更贴近本义
    让ansbile和docker愉快的在一起
    elasearch基础教程
    markdown语法
    python 实用pickle序列化
    python 解析配置文件
    ansible状态管理
    haproxy官方配置文档地址
    ansible操作模块相关
  • 原文地址:https://www.cnblogs.com/cervusy/p/9588015.html
Copyright © 2011-2022 走看看