• Short But Scary 解题报告


    Short But Scary

    正解的离线分治+虚树的做法太神奇...搞不到

    搞一个菜一点的ddp写写,结果调了200年,下次一定写树剖不写lct了,太难调了...

    大概就是按sub2那样维护

    你每个重链开一个线段树,然后链头把贡献扔给别的重链,然后每次在链上二分位置查一个和差不多了

    然后可以拿lct写

    但你得搞清楚翻转的时候要翻转的东西比较多,细节也比较多,异常的难写...

    算了懒得说了,给我毒瘤死了...


    Code:

    #include <cstdio>
    #include <cctype>
    #include <algorithm>
    #define ls ch[now][0]
    #define rs ch[now][1]
    #define fa par[now]
    const int N=1e5+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 head[N],to[N<<1],Next[N<<1],cnt;
    void add(int u,int v)
    {
        to[++cnt]=v,Next[cnt]=head[u],head[u]=cnt;
    }
    int n,m;
    int ch[N][2],par[N],tag[N];//翻转标记
    struct koito_yuu
    {
    	int siz,is,lef,dat,si;
    	//实际大小,子树全是,最左边的点是否是,与父亲关系,虚儿子贡献
    }yuu[2][N];
    int s[N],tot;
    bool isroot(int now){return ch[fa][0]==now||ch[fa][1]==now;}
    int identity(int now){return ch[fa][1]==now;}
    void connect(int f,int now,int typ){ch[fa=f][typ]=now;}
    void Reverse(int now)
    {
    	tag[now]^=1;
    	std::swap(yuu[0][now],yuu[1][now]);
    }
    void updata(int now)
    {
    	for(int k=0;k<=1;k++)
    	{
    		yuu[k][now].is=(yuu[k][ls].is&&yuu[k][now].dat&&yuu[k][rs].is);
    		yuu[k][now].siz=yuu[k][ls].siz;
    		if(ls)
            {
                yuu[k][now].lef=yuu[k][ls].lef;
                if(yuu[k][ls].is&&yuu[k][now].dat)
                {
                    yuu[k][now].siz+=yuu[k][now].si+1;
                    if(yuu[k][rs].lef) yuu[k][now].siz+=yuu[k][rs].siz;
                }
    		}
    		else
            {
                yuu[k][now].lef=yuu[k][now].dat;
                yuu[k][now].siz+=yuu[k][now].si+1;
                if(yuu[k][rs].lef) yuu[k][now].siz+=yuu[k][rs].siz;
            }
    	}
    }
    void pushdown(int now)
    {
    	if(tag[now])
    	{
    		if(ls) Reverse(ls);
    		if(rs) Reverse(rs);
    		tag[now]=0;
    	}
    }
    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)
    {
    	while(isroot(now)) s[++tot]=now,now=fa;
    	s[++tot]=now;
    	while(tot) pushdown(s[tot--]);
    	now=s[1];
    	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);
    		for(int k=0;k<=1;k++)
    		{
    			if(yuu[0][rs].lef)
    				yuu[k][now].si+=yuu[0][rs].siz;
    			if(yuu[0][las].lef)
    				yuu[k][now].si-=yuu[0][las].siz;
    		}
    		rs=las;
    		updata(now);
    	}
    }
    void dfs(int now,int f)
    {
    	yuu[0][now].is=yuu[0][now].lef=yuu[0][now].dat=1;
    	//yuu[1][now].is=yuu[1][now].lef=yuu[1][now].dat=1;
    	for(int v,i=head[now];i;i=Next[i])
    		if((v=to[i])!=f)
    			par[v]=now,dfs(v,now),yuu[0][now].si+=yuu[0][v].siz;
    	yuu[0][now].siz=yuu[0][now].si+1;
    	yuu[1][now].si=yuu[0][now].si;
    	yuu[1][now].siz=yuu[0][now].siz;
    }
    void modi(int u)
    {
    	access(u);
    	splay(u);
    	Reverse(u);
    }
    int query(int now)
    {
        pushdown(now);
    	if(!rs)
        {
            if(yuu[0][now].dat&&ls) return query(ls)+yuu[0][now].si+1;
            return yuu[0][now].si+1;
        }
    	if(yuu[0][rs].is)
    	{
    		int ret=yuu[0][now].si+1+yuu[0][rs].siz;
    		if(yuu[0][now].dat&&now!=1) ret+=query(ls);
    		return ret;
    	}
    	return query(rs);
    }
    int qry(int u)
    {
    	access(u);
    	splay(u);
    	return ((yuu[0][u].dat&&u!=1)?query(ch[u][0]):0)+yuu[0][u].si+1;
    }
    int main()
    {
        freopen("scary.in","r",stdin);
        freopen("scary.out","w",stdout);
    	yuu[1][1].dat=yuu[0][0].is=yuu[1][0].is=1;
    	read(n),read(m);
    	for(int u,v,i=1;i<n;i++) read(u),read(v),add(u,v),add(v,u);
    	dfs(1,0);
    	for(int op,u,v,i=1;i<=m;i++)
    	{
    		read(op);
    		if(op==1)
    		{
    			read(u),read(v);
    			modi(u),modi(v);
    		}
    		else
    		{
    			read(u);
    			printf("%d
    ",qry(u));
    		}
    	}
    	return 0;
    }
    

    2019.3.25

  • 相关阅读:
    解决Android Studio Gradle DSL method not found: 'android()'
    【转】关于ListView中notifyDataSetChanged()刷新数据不更新原因
    设计模式-单例模式
    IE浏览器让DIV居中
    Java通过DOM解析XML
    git 配置文件位置;git配置文件设置
    git config配置
    dos2unix
    文件的编码问题解决
    git diff old mode 100644 new mode 100755
  • 原文地址:https://www.cnblogs.com/butterflydew/p/10597011.html
Copyright © 2020-2023  润新知