zoukankan      html  css  js  c++  java
  • 「SHOI2014」三叉神经树 解题报告

    「SHOI2014」三叉神经树

    膜拜神仙思路

    我们想做一个类似于动态dp的东西,首先得确保我们的运算有一个交换律,这样我们可以把一长串的运算转换成一块一块的放到矩阵上之类的东西,然后拿数据结构维护。

    但是考虑这个题,它最下面的那个运算的输入端只有两种可能,于是我们只需要讨论一下初始输入就完事了。

    具体的,(LCT)每条实链维护一个(yuu[i][0/1])表示实链底端的点输入为(0/1)后链头输出什么。

    注意,这个链头指的是(splay)中那个点(i)的子树代表的那条链,也就是说链头是点(i)子树最左边的点。

    那么单独的一个点没有实儿子一定输入(0),因为最深的儿子没有实儿子,于是整个链的输入也是(0)

    当然我们肯定需要维护一个虚儿子的信息,它可以使某一条链(splay中的某子树)的输出为(1)然后再传给它的父亲之类的

    另外,(yuu)的全称是小糸侑((Koito Yuu))


    Code:

    #include <cstdio>
    #include <cctype>
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define fa par[now]
    const int N=2e6+10;
    template <class T>
    void read(T &x)
    {
    	x=0;char c=getchar();
    	while(!isdigit(c)) c=getchar();
    	while(isdigit(c)) x=x*10+c-'0',c=getchar();
    }
    int yuu[N][2],ch[N][2],par[N],bee[N],si[N],n,q;
    void updata(int now)
    {
    	yuu[now][0]=si[now]>1;
    	yuu[now][1]=si[now]>0;
    	if(rs)
    	{
    		if(yuu[rs][0]) yuu[now][0]=yuu[now][1];
    		else if(!yuu[rs][1]) yuu[now][1]=yuu[now][0];
    	}
    	if(ls)
    	{
    		if(yuu[now][0]) yuu[now][0]=yuu[now][1]=yuu[ls][1];
    		else if(!yuu[now][1]) yuu[now][0]=yuu[now][1]=yuu[ls][0];
    		else yuu[now][0]=yuu[ls][0],yuu[now][1]=yuu[ls][1];
    	}
    }
    int identity(int now){return ch[fa][1]==now;}
    int isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
    void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
    void Rotate(int now)
    {
    	int p=fa,typ=identity(now);
    	connect(p,ch[now][typ^1],typ);
    	if(isroot(p)) connect(par[p],now,identity(p));
    	else fa=par[p];
    	connect(now,p,typ^1);
    	updata(p),updata(now);
    }
    void splay(int now)
    {
    	for(;isroot(now);Rotate(now))
    		if(isroot(fa))
    			Rotate(identity(now)^identity(fa)?now:fa);
    }
    void access(int now)
    {
    	for(int las=0;now;las=now,now=fa)
    	{
    		splay(now),si[now]-=yuu[las][0],si[now]+=yuu[rs][0];
    		rs=las,updata(now);
    	}
    }
    int head[N],to[N],Next[N],cnt;
    void add(int u,int v)
    {
    	to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    void dfs(int now)
    {
    	if(now>n) return;
    	for(int i=head[now];i;i=Next[i])
    		dfs(to[i]),si[now]+=bee[to[i]];
    	bee[now]=yuu[now][0]=si[now]>1;
    	yuu[now][1]=si[now]>0;
    }
    int main()
    {
    	read(n);
    	for(int x,i=1;i<=n;i++)
    	{
    		read(x),par[x]=i,add(i,x);
    		read(x),par[x]=i,add(i,x);
    		read(x),par[x]=i,add(i,x);
    	}
    	for(int i=n+1;i<=3*n+1;i++) read(bee[i]);
    	dfs(1);
    	read(q);
    	for(int x,now,i=1;i<=q;i++)
    	{
    		read(x),now=par[x];
    		access(now),splay(now);
    		bee[x]^=1;
    		si[now]+=bee[x]?1:-1;
    		updata(now);
    		putchar(yuu[now][0]?'1':'0'),putchar('
    ');
    	}
    	return 0;
    }
    

    2019.2.24

  • 相关阅读:
    跟踪创建类的个数
    动手动脑3
    动手动脑:随机数发生器和函数重载
    统计英语文章中单词
    动手动脑(1)
    原码、反码、补码
    java测试ATM自助操作系统
    深入浅出 TCP/IP 协议栈
    十大经典排序算法(动图演示)
    深入浅出 Viewport 设计原理
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10426130.html
Copyright © 2011-2022 走看看