bzoj4764 弹飞大爷

我是萌萌的传送门

你们搞的这个题目啊,exciting!……

LCT裸题嘛。记得特判一下根节点所连出的边是否会成环就行了,还有删边的时候特判一下是否需要把这条边加回去。

几天不写LCT,结果一写就写出各种脑残错误,我怎么这么菜,233……

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define isroot(x) ((x)->p==null||((x)->p->ch[0]!=(x)&&(x)->p->ch[1]!=(x)))
  5 #define dir(x) ((x)==(x)->p->ch[1])
  6 using namespace std;
  7 const int maxn=200010;
  8 struct node{
  9     int size;
 10     node *ch[2],*p,*go;
 11     node():size(1){}
 12     inline void refresh(){size=ch[0]->size+ch[1]->size+1;}
 13 }null[maxn];
 14 void newnode(node*);
 15 node *access(node*);
 16 void link(node*,node*);
 17 void cut(node*);
 18 node *getroot(node*);
 19 void splay(node*);
 20 void rot(node*,int);
 21 int n,m,a[maxn],d,x;
 22 int main(){
 23     newnode(null);
 24     null->size=0;
 25     scanf("%d%d",&n,&m);
 26     for(int i=1;i<=n;i++)newnode(null+i);
 27     for(int i=1;i<=n;i++){
 28         scanf("%d",&a[i]);
 29         if(i+a[i]>0&&i+a[i]<=n)link(null+i,null+i+a[i]);
 30     }
 31     while(m--){
 32         scanf("%d%d",&d,&x);
 33         if(d==1){
 34             node *y=getroot(null+x);
 35             if(y->go!=null)printf("-1\n");
 36             else printf("%d\n",y->size);
 37         }
 38         else{
 39             cut(null+x);
 40             scanf("%d",&a[x]);
 41             if(x+a[x]>0&&x+a[x]<=n)link(null+x,null+x+a[x]);
 42         }
 43     }
 44     return 0;
 45 }
 46 inline void newnode(node *x){x->ch[0]=x->ch[1]=x->p=x->go=null;}
 47 node *access(node *x){
 48     node *y=null;
 49     while(x!=null){
 50         splay(x);
 51         x->ch[1]=y;
 52         (y=x)->refresh();
 53         x=x->p;
 54     }
 55     return y;
 56 }
 57 void link(node *x,node *y){//此时x一定是所在树的根
 58     if(getroot(y)==x)x->go=y;
 59     else{
 60         splay(x);
 61         x->p=y;
 62     }
 63 }
 64 void cut(node *x){
 65     access(x);
 66     splay(x);
 67     if(x->ch[0]==null)x->go=null;//如果它是根,那么这个操作只可能是断掉成环的这条边
 68     else{
 69         node *y=getroot(x);
 70         splay(x);
 71         x->ch[0]->p=null;
 72         x->ch[0]=null;
 73         x->refresh();
 74         if(getroot(y->go)==x){//说明它在环上
 75             link(y,y->go);
 76             y->go=null;
 77         }
 78     }
 79 }
 80 node *getroot(node *x){
 81     x=access(x);
 82     while(x->ch[0]!=null)x=x->ch[0];
 83     splay(x);
 84     return x;
 85 }
 86 void splay(node *x){
 87     while(!isroot(x)){
 88         if(isroot(x->p)){
 89             rot(x->p,dir(x)^1);
 90             break;
 91         }
 92         if(dir(x)==dir(x->p))rot(x->p->p,dir(x->p)^1);
 93         else rot(x->p,dir(x)^1);
 94         rot(x->p,dir(x)^1);
 95     }
 96 }
 97 void rot(node *x,int d){
 98     node *y=x->ch[d^1];
 99     if((x->ch[d^1]=y->ch[d])!=null)y->ch[d]->p=x;
100     y->p=x->p;
101     if(!isroot(x))x->p->ch[dir(x)]=y;
102     (y->ch[d]=x)->p=y;
103     x->refresh();
104     y->refresh();
105 }

大力踩了一发标程,哈哈……(装B

我能说这题我早就想出出来了嘛……真是尴尬= =

看你们这么会玩,我也想在bzoj上出题了233……(这货肯定会出毒瘤题报复社会……

时间: 2024-12-24 10:48:20

bzoj4764 弹飞大爷的相关文章

【LCT维护基环内向树森林】BZOJ4764 弹飞大爷

4764: 弹飞大爷 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 101  Solved: 52[Submit][Status][Discuss] Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了 第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里

bzoj4764 弹飞大爷 LCT

题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4764 题解 如果 \(a_i > 0\) 的话,那么就是 bzoj2002 的原题.直接用 LCT 维护就可以了. 但是现在这个题因为 \(a_i\) 任意,所以不能保证每个点向弹向的点连边一定是一棵树. 但是因为每个点的出边只有一条,所以一定是基环树森林. 考虑如何用 LCT 维护基环树. 首先这个环一定出现在根的位置.所以不妨用一个变量存一下这个根有没有额外的环边. link 的时候,如

bzoj4764: 弹飞大爷 link-cut-tree

题目传送门 这道题啊 调了一个晚上 因为写的是一个有根树和n个基环的写法 所以写得很奇怪..... 最后发现单独处理树的时候不能随意改变S(就是原来的根)不然size会出错.... #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int M=250007; int read(){ int ans=0,f=1

【BZOJ4764】弹飞大爷 LCT

[BZOJ4764]弹飞大爷 Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里,其中ai就是第i个小伙伴的力量值,也就是序列的第i项.然而,因为大爷太沉了,所以有些小伙伴不能撑到锻(you)炼(xi)结束,所以我们中途会替换一些小伙伴,也就是改变序列的

BZOJ 4764: 弹飞大爷

4764: 弹飞大爷 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 4  Solved: 4[Submit][Status][Discuss] Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们 决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了 第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里,其中

【bzoj 4764】弹飞大爷

Description 自从WC退役以来,大爷是越来越懒惰了.为了帮助他活动筋骨,也是受到了弹飞绵羊一题的启发,机房的小伙伴们决定齐心合力构造一个下面这样的序列.这个序列共有N项,每项都代表了一个小伙伴的力量值,如果大爷落到了第i个小伙伴的手里,那么第i个小伙伴会把大爷弹到第i+ai个小伙伴手里,其中ai就是第i个小伙伴的力量值,也就是序列的第i项.然而,因为大爷太沉了,所以有些小伙伴不能撑到锻(you)炼(xi)结束,所以我们中途会替换一些小伙伴,也就是改变序列的某些项.而且,因为大爷太沉了,

【BZOJ】4764 弹飞大爷

[算法]Link-Cut Tree [题意]一个n个数字组成的序列,a[i]表示移动到i+a[i]处,序列值可动态修改,求从i处开始移动到序列外的最小步数. [题解]将序列视为n个点,外界视为n+1,则每个点有且只有一条边连出去,由该性质可知是一个基环内向森林,问题转化为支持插入删除边并求点(n+1)到点i的距离. 由基环内向森林以及点n+1不能向外出边可知点n+1必然在无环的树上,所以若出现环则输出-1.

【bzoj 2002】弹飞绵羊

Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏.游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹飞.绵羊想知道当它从第i个装置起步时,被弹几次后会被弹飞.为了使得游戏更有趣,Lostmonkey可以修改某个弹力装置的弹力系数,任何时候弹力系数均为正整数. Input 第一行

AC日记——[HNOI2010]BOUNCE 弹飞绵羊 洛谷 P3203

[HNOI2010]BOUNCE 弹飞绵羊 思路: SBlct: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 200005 int n,m,f[maxn],ch[maxn][2],rev[maxn],ki[maxn],sta[maxn],top,lit,size[maxn]; inline void in(int &now) { char Cget=getchar();now=0; while(Cget&