zoukankan      html  css  js  c++  java
  • 【刷题】BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊

    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

    Solution

    转换成LCT的思路还是巧妙的

    我们把每个点要弹到的点向这个点连一条边,因为一个点弹到的点是固定的,所以这样连完后的图是一棵树

    然后我们发现对于题目的两个操作

    第一个查询操作,就是求树上一条链的长度,也可以说是大小

    第二个修改操作,就是把树上的一条边断掉,然后重连一条边

    这两个东西,一看就可以用LCT

    然后就LCT了

    一开始我是照着板子打了一个LCT,但是T掉了

    因为正宗的LCT对于这道题有很多多余的操作

    我们只要access,splay,nroot,rotate和pushup,当然也可以说还有一个简易的link

    因为删边一定存在,所以可以直接删除,而删边加边的点是同一个点,两个操作简化后和在一起就可以了

    其实这道题LCT维护的是一个森林,这个有点难理解

    #include<bits/stdc++.h>
    #define ll long long
    #define db double
    #define ld long double
    #define lc(x) ch[(x)][0]
    #define rc(x) ch[(x)][1]
    const int MAXN=200000+10;
    int n,m,A[MAXN];
    struct LCT{
    	int ch[MAXN][2],fa[MAXN],sum[MAXN];
    	inline void init()
    	{
    		memset(ch,0,sizeof(ch));
    		memset(fa,0,sizeof(fa));
    		memset(sum,0,sizeof(sum));
    	}
    	inline bool nroot(int x)
    	{
    		return lc(fa[x])==x||rc(fa[x])==x;
    	}
    	inline void pushup(int x)
    	{
    		sum[x]=sum[lc(x)]+sum[rc(x)]+1;
    	}
    	inline void rotate(int x)
    	{
    		int f=fa[x],p=fa[f],c=(rc(f)==x);
    		if(nroot(f))ch[p][rc(p)==f]=x;
    		fa[ch[f][c]=ch[x][c^1]]=f;
    		fa[ch[x][c^1]=f]=x;
    		fa[x]=p;
    		pushup(f);
    		pushup(x);
    	}
    	inline void splay(int x)
    	{
    		for(register int y=fa[x];nroot(x);rotate(x),y=fa[x])
    			if(nroot(y))rotate((lc(y)==x)==(lc(fa[y]==y))?y:x);
    		pushup(x);
    	}
    	inline void access(int x)
    	{
    		for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x);
    	}
    };
    LCT T;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char c='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(c!='')putchar(c);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    int main()
    {
    	read(n);
    	for(register int i=1;i<=n;++i)read(A[i]);
    	T.init();
    	for(register int i=1;i<=n;++i)
    		if(A[i]+i<=n)T.fa[i]=A[i]+i;
    	read(m);
    	while(m--)
    	{
    		int opt;
    		read(opt);
    		if(opt==1)
    		{
    			int pos;
    			read(pos);
    			pos++;
    			T.access(pos);T.splay(pos);
    			write(T.sum[pos],'
    ');
    		}
    		if(opt==2)
    		{
    			int pos,k;
    			read(pos);read(k);
    			pos++;A[pos]=k;
    			T.access(pos);T.splay(pos);
    			T.lc(pos)=T.fa[T.lc(pos)]=0;
    			if(A[pos]+pos<=n)T.fa[pos]=A[pos]+pos;
    			T.pushup(pos);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    操作系统-进程(1)进程与进程调度
    算法-图(6)广度优先遍历图
    网络摄像头RTSP流媒体协议视频平台EasyNVR如何进行延迟测试?
    【方案搭建】如何通过RTSP协议视频平台EasyNVR架设智慧城市实景终端展现方案?
    【解决方案】如何通过RTSP流媒体协议视频平台EasyNVR搭建智慧景区远程视频监管平台?
    7-12 排序 (25分)
    7-36 社交网络图中结点的“重要性”计算 (30分)-floyd最短路径
    7-35 城市间紧急救援 (25分)-dijkstra最短路径
    7-34 任务调度的合理性 (25分)--拓扑排序
    7-33 地下迷宫探索 (30分)--DFS
  • 原文地址:https://www.cnblogs.com/hongyj/p/8681601.html
Copyright © 2011-2022 走看看