bzoj3553: [Shoi2014]三叉神经树 树链剖分

70 篇文章 0 订阅
44 篇文章 0 订阅

此题的完成,代表近期的树链剖分就告一段落,全力进入联赛复习。

省选day2 的第二题,当时只是写了裸的bfs,TE到家了。

4个月后学长偶然的一句:树链剖分也可以,考试的时候就vfk一个人想到了。。。

如今看来,vfk走出考场说“今天三个题都是暴力”,是正确的。

由于每次改变根节点,那么这个到1的路径上的点才有可能更新。

当根节点由0变为1时,只会对上一个节点是1的点有影响,如果不是1直接更新这个点就可以了。

反过来 一个根节点由1变为0时,只会对上一个节点是2的产生影响。

val记录这个点有几个值为1的儿子

可是线段树如何介入呢。

这就是vfk的那句暴力了。

如果这个点由0变为了1,那么他所有的父节点中连续的只有一个子节点为1 即val[ i ]==1的点的值都会变为1;

如果这个点由1变为了0,那么他所有的父节点中连续的只有两个子节点为1 即val[ i ]==2的点的值都会变为0;

(建议自己画个图看一下)

这里就把O(n)的修改降为了O(logn);

所以线段树只需维护区间左右连续的值的长度即可。

每一次update后都要判断有没有到根节点。


/**************************************************************
    Problem: 3553
    User: xujiahe
    Language: C++
    Result: Accepted
    Time:23080 ms
    Memory:175812 kb
****************************************************************/
 
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define maxn 2100000
#define ll long long
#define lson rt<<1,l,m
#define rson rt<<1|1,m+1,r
#define  ss printf("orz\n")
inline int readint()
{
    int flag=0;
    char ch = getchar();
    int data = 0;
    while (ch < '0' || ch > '9')
    {
        if(ch=='-') flag=1;
        ch = getchar();
    }
    do
    {
        data = data*10 + ch-'0';
        ch = getchar();
    }while (ch >= '0' && ch <= '9');
        if(flag) data=-data;
    return data;
}
int fa[maxn],siz[maxn],top[maxn],w[maxn],son[maxn],dep[maxn],id,dy[maxn],nn,val2[maxn];
struct node
{
    int v,next;
}g[maxn];
int num,n,first[maxn],val[maxn];
int tree[maxn],col[maxn],lcol[maxn],rcol[maxn],lmax[maxn],rmax[maxn],sum[maxn];
void build(int a,int b)
{
    num++;
    g[num].v=b;
    g[num].next=first[a];
    first[a]=num;
}
void dfs(int now)
{
    if (now>nn) return;
    int v,ceng;
    int maxv=0,flag=0,tmp=0;
    siz[now]=1;
    for(int i=first[now];i;i=g[i].next)
    {
        v=g[i].v;
        if(v==fa[now]) continue;
        dfs(v);
        dep[v]=dep[now]+1;
        fa[v]=now;
        val2[now]+=val[v];
        if(val[v])
        {
            tmp++;
        }
        siz[now]+=siz[v];
        if(siz[v]>maxv)
        {
            maxv=siz[v];
            flag=v;
        }
    }
    son[now]=flag;
    if(tmp>1)
        val[now]=1;
    else
        val[now]=0;
}
void getid(int now,int root)
{
    if(now>nn) return;
    w[now]=++id;
    top[now]=root;
    dy[id]=now;
    if(son[now]) getid(son[now],top[now]);
    for(int i=first[now]; i; i=g[i].next)
    {
        if(g[i].v!=son[now]&&g[i].v!=fa[now])
        {
            getid(g[i].v,g[i].v);
        }
    }
}
void pushdown(int rt)
{
    if(col[rt]!=0)
    {
        col[rt<<1]+=col[rt];
        col[rt<<1|1]+=col[rt];
        lcol[rt<<1]+=col[rt];
        rcol[rt<<1]+=col[rt];
        lcol[rt<<1|1]+=col[rt];
        rcol[rt<<1|1]+=col[rt];
        col[rt]=0;
    }
}
void pushup(int rt,int len)
{
    lmax[rt]=lmax[rt<<1];
    if(lmax[rt<<1]==(len-(len>>1))&&rcol[rt<<1]==lcol[rt<<1|1])
    {
        lmax[rt]+=lmax[rt<<1|1];
    }
    rmax[rt]=rmax[rt<<1|1];
    if(rmax[rt<<1|1]==(len>>1)&&rcol[rt<<1]==lcol[rt<<1|1])
    {
        rmax[rt]+=rmax[rt<<1];
    }
     
    lcol[rt]=lcol[rt<<1];
    rcol[rt]=rcol[rt<<1|1];
}
void buildt(int rt,int l,int r)
{
    int m=(l+r)>>1;
    if(l==r)
    {
        lmax[rt]=rmax[rt]=1;
        lcol[rt]=rcol[rt]=val2[dy[l]];
        return ;
    }
    buildt(lson);
    buildt(rson);
    pushup(rt,r-l+1);
}
int getval(int rt,int l,int r,int x)
{
    int m=(l+r)>>1;
    if(l==r)
    {
        return lcol[rt];
    }
    pushdown(rt);
    if(x<=m)
    {
        return getval(lson,x);
    }
    else
    {
        return getval(rson,x);
    }
 
}
int getlen(int rt,int l,int r,int x,int y)
{
    if(x==l&&y==r)
    {
        return rmax[rt];
    }
    pushdown(rt);
    int tmp=0;
    int m=(l+r)>>1;
    if(y<=m)
    {
        return getlen(lson,x,y);
    }
    else if(x>m)
    {
        return getlen(rson,x,y);
    }
    else
    {
        tmp=getlen(rson,m+1,y);
        if (tmp<y-m||rcol[rt<<1]!=lcol[rt<<1|1]) return tmp;
        else return tmp+getlen(lson,x,m);
    }
}
void update(int rt,int l,int r,int x,int y,int c)
{
    if(x==l&&y==r)
    {
        lcol[rt]+=c;
        rcol[rt]+=c;
        col[rt]+=c;
        return;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(y<=m)
    {
        update(lson,x,y,c);
    }
    else if(x>m)
    {
        update(rson,x,y,c);
    }
    else
    {
        update(lson,x,m,c);
        update(rson,m+1,y,c);
    }
    pushup(rt,r-l+1);
}
void getans(int x,int op)
{
    int xx=x;
    if(op==1)
    {
        while(x)
        {
            if(getval(1,1,n,w[x])!=1)
            {
                update(1,1,n,w[x],w[x],1);
                break;
            }
            int len=getlen(1,1,n,w[top[x]],w[x]);
            update(1,1,n,max(w[x]-len+1,1),w[x],1);
            if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1)
            {
                update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],1);
            }
            if (len!=w[x]-w[top[x]]+1) break;
            x=fa[top[x]];
        }
    }
    else
    {
        while(x)
        {
            if(getval(1,1,n,w[x])!=2)
            {
                update(1,1,n,w[x],w[x],-1);
                break;
            }
            int len=getlen(1,1,n,w[top[x]],w[x]);
            update(1,1,n,max(w[x]-len+1,1),w[x],-1);
            if (max(w[x]-len+1,1)!=1 && len!=w[x]-w[top[x]]+1)
            {
                update(1,1,n,w[fa[dy[w[x]-len+1]]],w[fa[dy[w[x]-len+1]]],-1);
            }
            if (len!=w[x]-w[top[x]]+1) break;
            x=fa[top[x]];
        }
    }
}
int main()
{
    char str[20];
    int a,b,c,m;
    n=readint();
    nn=n;
    for(int i=1;i<=n;i++)
    {
        a=readint();
        b=readint();
        c=readint();
        build(i,a);
        build(i,b);
        build(i,c);
    }
    for(int i=1;i<=2*n+1;i++)
    {
        val[i+n]=readint();
    }
    n=n*3+1;
    fa[1]=0;
    dfs(1);
    getid(1,1);
    int x,y,z;
    n=nn;
    memset(col,0,sizeof(col));
    buildt(1,1,n);
    m=readint();
    while(m--)
    {
       x=readint();
       if(val[x]==0)
       {
           val[x]^=1;
           getans(fa[x],1);
       }
       else
       {
           val[x]^=1;
           getans(fa[x],2);
       }
       printf("%d\n",getval(1,1,n,1)>1);
    }
    return 0;
}
/*
3
2 3 4
5 6 7
8 9 10
0 0 0 0 1 1 1
5
4
4
5
6
8

1
0
0
1
1
*/



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值