zoukankan      html  css  js  c++  java
  • [HNOI2010]弹飞绵羊

    LCT的板子题

    蒟蒻看到很多大佬用分块的方法解决了这道题,但是本蒟蒻不会分块,但我会LCT啊,所以就用LCT解决了这道题。

    神奇的思路

    对于每一个节点 维护他的size,每一个弹射器 由它即将到达的弹射器向他连边

    虚拟一个n+1号节点 进行最后一次弹射,
    每次直接查询对应位置的size即可。

    也就是

    把给出的数据当做森林,即i的父亲是i+k[i],询问的是到根的路径长度+1,可以修改父亲。所以只需要link操作即可,注意把超过n的节点设为0。每次询问先access,然后Splay到根(Splay中要维护size),这样所询问的答案就是节点在Splay上的左子树大小+1。

    CODE:

    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<cstdlib>
    #include<algorithm>
    
    using namespace std;
    
    const int maxn = 200010;
    
    inline int read(){
    	int x = 0;
    	int flag = true;
    	int k = getchar();
    	while(k != '-' && !isdigit(k))
    	    k = getchar();
    	if(k == '-'){
    	   k = getchar();
    	   flag = false;
    	}
    	while(isdigit(k)){
    		x = x * 10 + k - '0';
    		k = getchar();
    	}
    	return (flag ? x : -x);
    }
    
    struct node{
    	int father;
    	int ch[2];
    	int size;
    	bool is_root;
    }tree[maxn];
    
    int n,m,k[maxn];
    
    void update(int x){
    	tree[x].size=1;
    	if(tree[x].ch[0]) tree[x].size += tree[tree[x].ch[0]].size;
    	if(tree[x].ch[1]) tree[x].size += tree[tree[x].ch[1]].size;
    }
    inline int getson(int x){
    	return x == tree[tree[x].father].ch[1];
    }
    void rotate(int x){
    	if(tree[x].is_root) return;
    	int k = getson(x),fa = tree[x].father;
    	int fafa = tree[fa].father;
    	tree[fa].ch[k] = tree[x].ch[k^1];
    	if(tree[x].ch[k^1])
    		tree[tree[x].ch[k^1]].father = fa;
    	tree[x].ch[k^1] = fa;
    	tree[fa].father = x;
    	tree[x].father = fafa;
    	if(!tree[fa].is_root)
    		tree[fafa].ch[fa == tree[fafa].ch[1]] = x;
    	else {
    		tree[x].is_root = true;
    		tree[fa].is_root = false;
    	}
    	update(fa);
    	update(x);
    }
    void Splay(int x){
    	for(int y ; !tree[x].is_root;rotate(x)){
    		if(!tree[y = tree[x].father].is_root){
    			rotate((getson(x) == getson(y)) ? y : x);
    		}
    	}
    }
    void access(int x){
    	int y = 0;
    	while(x){
    		Splay(x);
    		tree[tree[x].ch[1]].is_root = true;
    		tree[tree[x].ch[1] = y].is_root = false;
    		update(x);
    		x = tree[y = x].father;
    	}
    }
    void link(int u,int v){
    	if(v > n) v = 0;
    	access(u);
    	Splay(u);
    	tree[tree[u].ch[0]].is_root = true;
    	tree[tree[u].ch[0]].father = 0;
    	tree[u].ch[0] = 0;
    	tree[u].father = v;
    	update(u);
    }
    int Query(int x){
    	access(x);
    	Splay(x);
    	return tree[tree[x].ch[0]].size + 1;
    }
    
    int main(){
    	n = read();
    	for(int i = 1 ; i <= n ; i++){
    		tree[i].is_root = 1;
    		tree[i].size = 1;
    		tree[i].father = 0;
    		tree[i].ch[0] = 0;
    		tree[i].ch[1] = 0;
    	}
    	for(int i = 1 ; i <= n ; i++){
    		k[i] = read();
    		link(i,i + k[i]);
    	}
    	m = read();
    	int xx,x,y;
    	while(m--){
    		xx = read();
    		x = read();
    		if(xx == 1)
    			printf("%d
    ",Query(x+1));
    		else if(xx == 2){
    			y = read();
    			link(x + 1,x + y + 1);
    		}
    	}
    	return 0;
    }
    

    另外,LCT的时间复杂度是(O(logn^2)),所以不开氧气优化也能过。
    蒟蒻的耗时为652ms。

  • 相关阅读:
    ADO.NET初学习
    phpstorm+xdeubg debugging 9000 is busy 提示端口不可以的处理办法
    mysql 乐观锁和悲观锁
    Laravel Facade 调用流程源码分析
    利用 反射ReflectionClass来查看里面的属性和方法
    PHP ArrayAccess 接口简单实例
    laravel service provider 简单实例
    从github 下载下来的PHP项目代码本地需要怎么部署
    PHP Closure 类的bind简介和使用
    PHP $this,self,static 的区别
  • 原文地址:https://www.cnblogs.com/Repulser/p/9600779.html
Copyright © 2011-2022 走看看