• BZOJ2002 弹飞绵羊


    这题可以用分块暴力做,这里给出正解LCT的代码。

    对于每一个弹射器i+k相当于i的父亲,大于n的全部归到n+1上。

    这样对于修改操作就像于换了个父亲,我们要记录下上一次的父亲因为在splay中父亲可能会改变。

    对于查询操作就相当于把n+1mroot到根,因为你添加时会更新,不能确保n+1的位置。

    而答案就是xsplay到根后左儿子的大小,因为你access操作是带着当前splay中比他浅的点一起上去的(一开始这里没有想明白)

    具体实现看代码吧

    By:大奕哥

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int N=2e5+5;
      4 int size[N],c[N][2],rev[N],fa[N],nex[N],n,m;
      5 bool isroot(int x){return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;}
      6 void pushdown(int x)
      7 {
      8     if(rev[x])
      9     {
     10         rev[c[x][0]]^=1;rev[c[x][1]]^=1;rev[x]^=1;
     11         swap(c[x][0],c[x][1]);
     12     }
     13     return;
     14 }
     15 void update(int x)
     16 {
     17     size[x]=size[c[x][0]]+size[c[x][1]]+1;
     18     return;
     19 }
     20 void rotate(int x)
     21 {
     22     int y=fa[x],z=fa[y],l,r;
     23     l=c[y][1]==x;r=l^1;
     24     if(!isroot(y))c[z][c[z][1]==y]=x;
     25     fa[x]=z;fa[y]=x;fa[c[x][r]]=y;
     26     c[y][l]=c[x][r];c[x][r]=y;
     27     update(y);update(x);
     28     return;
     29 }
     30 int s[N];
     31 void splay(int x)
     32 {
     33     int top=0;int i;
     34     for(i=x;!isroot(i);i=fa[i])s[++top]=i;s[++top]=i;
     35     for(int i=top;i;--i)pushdown(s[i]);
     36     while(!isroot(x))
     37     {
     38         int y=fa[x],z=fa[y];
     39         if(!isroot(y))
     40         {
     41             if(c[y][0]==x^c[z][0]==y)rotate(x);
     42             rotate(y);
     43         }
     44         rotate(x);
     45     }
     46     return;
     47 }
     48 void access(int x)
     49 {
     50     int y=0;
     51     while(x)
     52     {
     53         splay(x);
     54         c[x][1]=y;
     55         y=x;x=fa[x];
     56     }
     57     return;
     58 }
     59 void mroot(int x)
     60 {
     61     access(x);splay(x);rev[x]^=1;
     62 }
     63 void link(int x,int y)
     64 {
     65     mroot(x);fa[x]=y;splay(x);
     66 }
     67 void cut(int x,int y)
     68 {
     69     mroot(x);access(y);splay(y);c[y][0]=fa[x]=0;
     70 }
     71 int main()
     72 {
     73     scanf("%d",&n);int x,y,f;
     74     for(int i=1;i<=n;++i)
     75     {
     76         scanf("%d",&x);
     77         fa[i]=x+i;size[i]=1;
     78         if(fa[i]>n)fa[i]=n+1;
     79         nex[i]=fa[i];
     80     }
     81     size[n+1]=1;
     82     scanf("%d",&m);
     83     for(int i=1;i<=m;++i)
     84     {
     85         scanf("%d",&f);
     86         if(f==1)
     87         {
     88             mroot(n+1);
     89             scanf("%d",&x);x++;
     90             splay(x);int ans1=0;
     91             ans1+=size[c[x][0]];
     92             access(x);splay(x);
     93             printf("%d
    ",ans1+size[c[x][0]]);
     94         }
     95         else
     96         {
     97             scanf("%d%d",&x,&y);
     98             x++;y=min(n+1,x+y);
     99             cut(x,nex[x]);link(x,y);nex[x]=y;
    100         }
    101     }
    102     return 0;
    103 }
  • 相关阅读:
    [原]80386中断表
    [原]elf可执行连接文件格式
    [原]nasm语法
    VLAN基础配置及Access接口
    配置hybird接口
    配置Trunk接口
    [导入]Oracle常用技巧和脚本
    [导入]ORACLE 常用的SQL语法和数据对象
    [导入]Oracle 基本知识
    [导入]Oracle特殊包
  • 原文地址:https://www.cnblogs.com/nbwzyzngyl/p/8338068.html
Copyright © 2020-2023  润新知