山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

bzoj 2002 [Hnoi2010]Bounce 弹飞绵羊(LCT)

 

【题目链接】

 

    http://www.lydsy.com/JudgeOnline/problem.php?id=2002

 

【题意】

 

    给定n个数的序列,i可以跳到i+k[i],需要能够修改k并可以查询跳出n需要的步数。

 

【思路】

 

    把i->i+k看作一条边,则问题抽象为一个森林,越靠后的点离原树的根越近。

    考虑LCT维护大小siz。

    修改k的操作可以看作是断边与连边的操作。注意如果直接跳出n应该与null相连以切断原来的边。

  一次查询可以先Access使u到根的路径独立,然后splay将u调整至根查询siz。

 

【代码】

 

 

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 using namespace std;
 5 
 6 const int N = 4e5+10;
 7 
 8 namespace LCT {
 9     
10     struct Node {
11         Node *ch[2],*fa;
12         int siz;
13         Node();
14         void maintain() {
15             siz=ch[0]->siz+ch[1]->siz+1;
16         }
17     } *null=new Node,T[N];
18     Node::Node() { fa=ch[0]=ch[1]=null; siz=1; }
19     void rot(Node* o,int d) {
20         Node *p=o->fa;
21         p->ch[d]=o->ch[d^1];
22         o->ch[d^1]->fa=p;
23         o->ch[d^1]=p;
24         o->fa=p->fa;
25         if(p->fa->ch[0]==p) 
26             p->fa->ch[0]=o;
27         else if(p->fa->ch[1]==p)
28             p->fa->ch[1]=o;
29         p->fa=o;
30         p->maintain();
31     }
32     void splay(Node* o) {
33         Node *nf,*nff;
34         while(o->fa->ch[0]==o||o->fa->ch[1]==o) {
35             nf=o->fa,nff=nf->fa;
36             if(o==nf->ch[0]) {
37                 if(nf==nff->ch[0]) rot(nf,0);
38                 rot(o,0);
39             } else {
40                 if(nf==nff->ch[1]) rot(nf,1);
41                 rot(o,1);
42             }
43         }
44         o->maintain();
45     }
46     void Access(Node* o) {
47         Node *son=null;
48         while(o!=null) {
49             splay(o);
50             o->ch[1]=son;
51             o->maintain();
52             son=o; o=o->fa;
53         }
54     }
55     void Link(Node* u,Node* v) {
56         Access(u); splay(u);
57         u->ch[0]->fa=null;
58         u->ch[0]=null;
59         u->fa=v;
60         u->maintain();
61     }
62 
63 }
64 using namespace LCT;
65 
66 int n,m;
67 
68 int main()
69 {
70     null->fa=null->ch[0]=null->ch[1]=null;
71     null->siz=0;
72     scanf("%d",&n);
73     int op,x,y;
74     for(int i=1;i<=n;i++) {
75         scanf("%d",&x);
76         if(i+x<=n) T[i].fa=&T[i+x];
77     }
78     scanf("%d",&m);
79     for(int i=1;i<=m;i++) {
80         scanf("%d%d",&op,&x);
81         x++;
82         if(op==1) {
83             Access(&T[x]); splay(&T[x]);
84             printf("%d\n",T[x].siz);
85         } else {
86             scanf("%d",&y);
87             if(x+y<=n) Link(&T[x],&T[x+y]);
88             else Link(&T[x],null);
89         }
90     }
91     return 0;
92 }

 

posted on 2016-03-25 14:54  hahalidaxin  阅读(249)  评论(0编辑  收藏  举报