• [bzoj2002][Hnoi2010]Bounce 弹飞绵羊【LCT】


    【题目描述】

    Description

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

    Input

    第一行包含一个整数n,表示地上有n个装置,装置的编号从0到n-1,接下来一行有n个正整数,依次为那n个装置的初始弹力系数。第三行有一个正整数m,接下来m行每行至少有两个数i、j,若i=1,你要输出从j出发被弹几次后被弹飞,若i=2则还会再输入一个正整数k,表示第j个弹力装置的系数被修改成k。对于20%的数据n,m<=10000,对于100%的数据n<=200000,m<=100000

    Output

    对于每个i=1的情况,你都要输出一个需要的步数,占一行。

    Sample Input

    4
    1 2 1 1
    3
    1 1
    2 1 1
    1 1

    Sample Output

    2
    3

    HINT

    Source

    【题解】

     弹力装置的关系可看做一棵有根树(设跳出后进入n+1号节点),以n+1为根,LCT维护一下即可。

    /* --------------
        user Vanisher
        problem bzoj2002 lct 
    ----------------*/
    # include <bits/stdc++.h>
    # define 	ll 		long long
    # define 	N 		200010
    using namespace std;
    int read(){
    	int tmp=0, fh=1; char ch=getchar();
    	while (ch<'0'||ch>'9'){if (ch=='-') fh=-1; ch=getchar();}
    	while (ch>='0'&&ch<='9'){tmp=tmp*10+ch-'0'; ch=getchar();}
    	return tmp*fh;
    }
    struct Splay{
    	int pl,pr,size,tag,fa;
    }T[N];
    int k[N],n,m,st[N];
    void pushtag(int x){
    	if (x==0) return;
    	if (T[x].tag==1){
    		T[T[x].pl].tag^=1; T[T[x].pr].tag^=1;
    		swap(T[x].pl,T[x].pr);
    	}
    	T[x].tag=0;
    }
    void change(int x){
    	if (x==0) return;
    	T[x].size=1+T[T[x].pl].size+T[T[x].pr].size;
    }
    bool isroot(int x){
    	return T[T[x].fa].pl!=x&&T[T[x].fa].pr!=x;
    }
    void zig(int x){
    	int y=T[x].fa;
    	if (!isroot(y)){
    		if (T[T[y].fa].pl==y)  T[T[y].fa].pl=x; else T[T[y].fa].pr=x;
    	}
    	T[x].fa=T[y].fa;
    	T[y].pl=T[x].pr; T[T[x].pr].fa=y;
    	T[x].pr=y; T[y].fa=x; 
    	change(y); change(x);
    }
    void zag(int x){
    	int y=T[x].fa;
    	if (!isroot(y)){
    		if (T[T[y].fa].pl==y)  T[T[y].fa].pl=x; else T[T[y].fa].pr=x;
    	}
    	T[x].fa=T[y].fa;
    	T[y].pr=T[x].pl; T[T[x].pl].fa=y;
    	T[x].pl=y; T[y].fa=x; 
    	change(y); change(x);
    }
    void splay(int x){
    	int y=x,top=1; st[1]=x;
    	while (!isroot(y)) st[++top]=T[y].fa, y=T[y].fa;
    	for (int i=top; i>=1; i--) pushtag(st[i]);
    	while (!isroot(x)){
    		int y=T[x].fa;
    		if (isroot(y))
    			if (T[y].pl==x) zig(x); else zag(x);
    			else if (T[T[y].fa].pl==y)
    				if (T[y].pl==x) zig(y), zig(x);
    					else zag(x), zig(x);
    				else if (T[y].pl==x) zig(x), zag(x);
    					else zag(y), zag(x);
    	}
    }
    void access(int u){
    	int v=0;
    	while (u){
    		splay(u); 
    		T[u].pr=v; T[v].fa=u;
    		change(u);
    		v=u;
    		u=T[u].fa;
    	}
    }
    void makeroot(int u){
    	access(u);
    	splay(u);
    	T[u].tag^=1;
    }
    void link(int u, int v){
    	makeroot(u);
    	T[u].fa=v; 
    }
    void cut(int u, int v){
    	makeroot(u);
    	access(v);
    	splay(v);
    	T[v].pl=T[u].fa=0; 
    	change(v);
    }
    int query(int u){
    	makeroot(n+1);
    	access(u);
    	splay(u);
    	return T[T[u].pl].size;
    }
    int main(){
    	n=read();
    	for (int i=1; i<=n+1; i++) T[i].size=1;
    	for (int i=1; i<=n; i++){
    		k[i]=read();
    		if (i+k[i]>n) k[i]=n+1-i;
    		link(i,i+k[i]);	
    	}
    	m=read();
    	for (int i=1; i<=m; i++){
    		int opt=read(), u=read()+1;
    		if (opt==1) printf("%d
    ",query(u));
    		else {
    			cut(u,u+k[u]);
    			k[u]=read();
    			if (u+k[u]>n) k[u]=n+1-u;
    			link(u,u+k[u]);
    		}
    	}
    	return 0;
    }


  • 相关阅读:
    mysql02-mysql的json操作函数
    一个mysql表最多可以有几列? 一个mysql表最多可以创建多少个索引? 单个索引最多可以包含多少个列? 一个索引最多可以有多长?这个几个问题你都不一定知道正确答案
    转载-mysql 数据库的设计三范式
    转载-Java 为什么是值传递
    Navicat远程连接不上mysql解决方案
    windows系统如何查看端口被占用、杀进程
    mysql01-mysql基础知识
    mysql 远程连接速度慢的解决方案
    centos8 安装 jdk
    CentOS8下安装mysql8
  • 原文地址:https://www.cnblogs.com/Vanisher/p/9136043.html
Copyright © 2020-2023  润新知