zoukankan      html  css  js  c++  java
  • 【洛谷P3203】[HNOI2010]弹飞绵羊【LCT】

    传送门

    Solution

    我们把一次从\(i\)向后弹到\(i+k_i\)看作是连了一条边,如果\(i+k_i>n\)也就是被弹飞了,我们就认为被弹到了一个特殊节点\(n+1\)

    于是就直接维护\(Splay\)上子树的\(siz\),查询从\(x\)起步,就拉出从\(x\)\(n+1\)\(Splay\),将\(n+1\)置为根,然后输出\(n+1\)维护的\(siz\)即可

    更改弹力系数就是先\(cut\)\(link\)

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N=4e5+10;
    int n,siz[N],ch[N][2],fa[N],rev[N];
    inline bool which(int x){return ch[fa[x]][1]==x;}
    inline void pushup(int x){
    	siz[x]=siz[ch[x][0]]+siz[ch[x][1]]+1;
    }
    inline bool isroot(int x){return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline void rever(int x){
    	swap(ch[x][0],ch[x][1]);
    	rev[x]^=1;
    }
    inline void pushdown(int x){
    	if(!rev[x]) return ;
    	if(ch[x][0]) rever(ch[x][0]);
    	if(ch[x][1]) rever(ch[x][1]);
    	rev[x]=0;
    }
    inline void Rotate(int x){
    	int y=fa[x],z=fa[y],wx=which(x),wy=which(y);
    	if(!isroot(y)) ch[z][wy]=x;fa[x]=z;
    	ch[y][wx]=ch[x][wx^1];
    	if(ch[y][wx]) fa[ch[y][wx]]=y;
    	ch[x][wx^1]=y;fa[y]=x;
    	pushup(y);
    }
    int stk[N],top;
    inline void Splay(int x){
    	int now=x;
    	stk[top=1]=now;
    	while(!isroot(now)) now=fa[now],stk[++top]=now;
    	while(top) pushdown(stk[top--]);
    	while(!isroot(x)){
    		int y=fa[x];
    		if(!isroot(y)){
    			if(which(x)==which(y)) Rotate(y);
    			else Rotate(x);
    		}Rotate(x);
    	}
    	pushup(x); 
    } 
    inline void access(int x){
    	for(int last=0;x;last=x,x=fa[x])
    		Splay(x),ch[x][1]=last,pushup(x);
    }
    inline void makeroot(int x){
    	access(x);Splay(x);
    	rever(x);
    }
    inline int findroot(int x){
    	access(x);Splay(x);
    	while(ch[x][0]) pushdown(x),x=ch[x][0];
    	Splay(x);
    	return x;
    }
    inline void split(int x,int y){
    	makeroot(x);access(y);
    	Splay(y);
    }
    inline void link(int x,int y){
    	makeroot(x);
    	fa[x]=y;
    }
    inline void cut(int x,int y){
    	split(x,y);
    	fa[x]=ch[y][0]=0;
    	pushup(y);
    }
    int v[N],m,cnt=0;
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;++i){
    		scanf("%d",&v[i]);
    		v[i]+=i;
    		if(v[i]>n) v[i]=n+1;
    		link(i,v[i]);
    	}
    	scanf("%d",&m);
    	for(int i=1;i<=m;++i){
    		int op,x,y;
    		scanf("%d%d",&op,&x);++x;
    		if(op==1){
    			split(x,n+1);
    			printf("%d\n",siz[n+1]-1); 
    		}
    		else{
    			scanf("%d",&y);
    			int nw=y+x;if(nw>n) nw=n+1;
    			if(nw==v[x]) continue;
    			else cut(x,v[x]),v[x]=nw,link(x,v[x]);
    		}
    	} 
    	return 0;
    }
    
  • 相关阅读:
    ioS开发之CoreLocation(GPS定位)
    iOSiOS开发之退出功能(易错)
    iOS开发之判断横竖屏切换
    iOS开发之左右抖动效果
    iOS开发之UIPopoverController
    thinkphp or查询
    Invalid left-hand side in assignment
    实现input表单从右向左输入
    thinkPhp不为空查询
    array_filter()用法
  • 原文地址:https://www.cnblogs.com/tqxboomzero/p/14243245.html
Copyright © 2011-2022 走看看