• 【bzoj 4764】弹飞大爷


    Description

    自从WC退役以来,大爷是越来越懒惰了。为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列。这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里,其中ai就是第i个小伙伴的力量值,也就是序列的第i项。然而,因为大爷太沉了,所以有些小伙伴不能撑到锻(you)炼(xi)结束,所以我们中途会替换一些小伙伴,也就是改变序列的某些项。而且,因为大爷太沉了,所以有些小伙伴不能把大爷扔向前方,而是会把大爷往反方向扔,也就是序列中的一些项会是负的(当然,也可能是零喽)。现在机智的大爷通过在空中的观察,已经知道小伙伴们的所有活动——即初始序列、所有更改操作,他想请你算一算,如果他在某时刻落到了某个位置,那么他会在几次弹起之后落到小伙伴序列之外(毕竟摔在地上还是蛮疼的)。

    Input

    第一行为两个整数N和M,代表序列长度和操作次数。
    第二行为N个整数,代表初始的小伙伴序列。
    接下来有M行,每行代表一个操作。
    如果这一行的第一个数是1,代表该操作是一个询问操作,接下来一个数X,代表询问此时大爷从X处,经过几次弹起会摔在地上。如果永远不会摔在地上,请输出-1。
    如果这一行的第一个数是2,代表该操作是一个更改操作,接下来两个数X,Y,代表将序列的第X项改为Y。
    N,M <= 200000  |Ai| < N

    Output

    对于每次询问操作,输出弹起次数或-1。

    Sample Input

    3 19
    1 1 1
    1 1
    1 2
    1 3
    2 1 2
    1 1
    1 2
    1 3
    2 3 -1
    1 1
    1 2
    1 3
    2 2 233
    1 1
    1 2
    1 3
    2 2 -233
    1 1
    1 2
    1 3

    Sample Output

    3
    2
    1
    2
    2
    1
    -1
    -1
    -1
    3
    1
    2
    3
    1
    2

     

    调了两天终于A了……万分感谢czl大爷、cyc大爷和yy大爷。

    RE了几发之后一直调不出来,心态爆炸开始乱搞,然后就WA了。怪我自己没有理解好写法。

    因为有环,所以需要隐藏环上的一条边来使其成为森林,hl数组与hr数组即代表隐藏边的端点。

    剩下的直接上代码……

     

      1 #include<cstdio>
      2 #include<cstring>
      3 #include<algorithm>
      4 using namespace std;
      5 const int N=200050;
      6 int n,m,t,u,v,a[N],hl[N],hr[N],st[N];
      7 struct node{int fa,c[2],s;bool rev;}tr[5*N];
      8 int read()
      9 {
     10     int x=0,f=1;char c=getchar();
     11     while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
     12     while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
     13     return x*f;
     14 }
     15 bool isroot(int k){return !k||!tr[k].fa||(tr[tr[k].fa].c[0]!=k&&tr[tr[k].fa].c[1]!=k);}
     16 void up(int k){tr[k].s=tr[tr[k].c[0]].s+tr[tr[k].c[1]].s+1;}
     17 void down(int k)
     18 {
     19     int l=tr[k].c[0],r=tr[k].c[1];
     20     if(tr[k].rev)
     21     {
     22         tr[k].rev^=1;tr[l].rev^=1;tr[r].rev^=1;
     23         swap(tr[k].c[0],tr[k].c[1]);
     24     }
     25     if(l)hl[l]=hl[k],hr[l]=hr[k];
     26     if(r)hl[r]=hl[k],hr[r]=hr[k];
     27 }
     28 void rotate(int x)
     29 {
     30     int y=tr[x].fa,z=tr[y].fa,l,r;
     31     if(tr[y].c[0]==x)l=0;else l=1;r=l^1;
     32     if(!isroot(y)){if(tr[z].c[0]==y)tr[z].c[0]=x;else tr[z].c[1]=x;}
     33     tr[x].fa=z;tr[y].fa=x;tr[tr[x].c[r]].fa=y;
     34     tr[y].c[l]=tr[x].c[r];tr[x].c[r]=y;
     35     up(y);up(x);
     36 }
     37 void splay(int x)
     38 {
     39     int top=0;st[++top]=x;
     40     for(int i=x;!isroot(i);i=tr[i].fa)st[++top]=tr[i].fa;
     41     for(int i=top;i;i--)down(st[i]);
     42     while(!isroot(x))
     43     {
     44         int y=tr[x].fa,z=tr[y].fa;
     45         if(!isroot(y))
     46         {
     47             if((tr[y].c[0]==x)^(tr[z].c[0]==y))rotate(x);
     48             else rotate(y);
     49         }
     50         rotate(x);
     51     }
     52 }
     53 void acs(int x)
     54 {
     55     int t=0;
     56     while(x){splay(x);tr[x].c[1]=t;up(x);t=x;x=tr[x].fa;}
     57 }
     58 void mkroot(int x){acs(x);splay(x);tr[x].rev^=1;}
     59 int find(int x){acs(x);splay(x);while(tr[x].c[0])x=tr[x].c[0];return x;}
     60 void link(int x,int y){mkroot(x);tr[x].fa=y;acs(x);splay(x);}
     61 void cut(int x,int y)
     62 {
     63     mkroot(x);acs(y);splay(y);
     64     tr[x].fa=tr[y].c[0]=0;up(y);
     65     hl[x]=hr[x]=hl[y]=hr[y]=0;
     66 }
     67 void xlink(int x,int y)
     68 {
     69     if(find(x)==find(y))hl[y]=x,hr[y]=y;
     70     else link(x,y);
     71 }
     72 void xcut(int x,int y)
     73 {
     74     acs(x);splay(x);int li=hl[x],ri=hr[x];
     75     if(hl[x]==x&&hr[x]==y)hl[x]=hl[y]=hr[x]=hr[y]=0;
     76     else
     77     {
     78         cut(x,y);
     79         if(li&&ri)xlink(li,ri);//划重点!xlink而不是link。
     80     }
     81 }
     82 int query(int x)
     83 {
     84     mkroot(n+1);acs(x);splay(x);
     85     if(hl[x]&&hr[x])return -1;
     86     return tr[x].s-1;
     87 }
     88 int main()
     89 {
     90     n=read();m=read();
     91     for(int i=1;i<=n+1;i++)tr[i].s=1;
     92     for(int i=1;i<=n;i++)
     93     {
     94         a[i]=read();
     95         if(i+a[i]<=0||i+a[i]>n)link(i,n+1);
     96         else xlink(i,i+a[i]);
     97     }
     98     while(m--)
     99     {
    100         t=read();
    101         if(t==1)u=read(),printf("%d
    ",query(u));
    102         else
    103         {
    104             u=read();v=read();
    105             if(u+a[u]<=0||u+a[u]>n)cut(u,n+1);
    106             else xcut(u,u+a[u]);
    107             if(u+v<=0||u+v>n)link(u,n+1);
    108             else xlink(u,u+v);
    109             a[u]=v;
    110         }
    111     }
    112     return 0;
    113 }
    View Code
  • 相关阅读:
    Python OpenCV 常用操作
    Conda Cheatsheet | 速查表
    Loadrunner解决启动浏览器后页面显示空白
    26个ASP.NET常用性能优化方法
    C# Foreach用法
    体验ASP.NET MVC3 表单令牌功能!
    基于.Net(C#开发)平台的三层框架架构软件的设计与实现
    去掉浏览器中a标签的虚线
    Microsoft Dynamics CRM 4.0 序列号
    编写 Cookie
  • 原文地址:https://www.cnblogs.com/zsnuo/p/7091464.html
Copyright © 2020-2023  润新知