BZOJ3637 Query on a tree VI(树链剖分+线段树)

  考虑对于每一个点维护子树内与其连通的点的信息。为了换色需要,记录每个点黑白两种情况下子树内连通块的大小。

  查询时,找到深度最浅的同色祖先即可,这可以比较简单的树剖+线段树乱搞一下(似乎就是qtree3)。换色会造成一个连通块分裂并产生新连通块,这只会影响到祖先节点的信息。同样树剖+线段树暴力改上去即可。

  因为写的实在太丑没有一个oj能过,darkbzoj上42个点跑到第38个T掉了。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int x=0,f=1;char c=getchar();
    while (c<'0'||c>'9') {if (c=='-') f=-1;c=getchar();}
    while (c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
    return x*f;
}
#define N 100010
int n,m,p[N],color[N],t=0;
int dfn[N],id[N],top[N],fa[N],son[N],size[N],cnt=0;
int L[N<<2],R[N<<2],tree[2][N<<2],lazy[2][N<<2],same[2][N<<2];
struct data{int to,nxt;
}edge[N<<1];
void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;}
void dfs1(int k)
{
    size[k]=1;color[k]=1;
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=fa[k])
    {
        fa[edge[i].to]=k;
        dfs1(edge[i].to);
        size[k]+=size[edge[i].to];
        if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to;
    }
}
void dfs2(int k,int from)
{
    id[k]=++cnt;dfn[cnt]=k;
    top[k]=from;
    if (son[k]) dfs2(son[k],from);
    for (int i=p[k];i;i=edge[i].nxt)
    if (edge[i].to!=fa[k]&&edge[i].to!=son[k]) dfs2(edge[i].to,edge[i].to);
}
void build(int k,int l,int r)
{
    L[k]=l,R[k]=r;same[1][k]=1;
    if (l==r){tree[1][k]=size[dfn[l]];tree[0][k]=1;return;}
    int mid=l+r>>1;
    build(k<<1,l,mid);
    build(k<<1|1,mid+1,r);
}
void down(int k)
{
    tree[0][k<<1]+=lazy[0][k],tree[0][k<<1|1]+=lazy[0][k];
    tree[1][k<<1]+=lazy[1][k],tree[1][k<<1|1]+=lazy[1][k];
    lazy[0][k<<1]+=lazy[0][k],lazy[0][k<<1|1]+=lazy[0][k];
    lazy[1][k<<1]+=lazy[1][k],lazy[1][k<<1|1]+=lazy[1][k];
    lazy[0][k]=lazy[1][k]=0;
}
int getsame(int k,int l,int r,int p)
{
    if (L[k]==l&&R[k]==r) return same[p][k];
    if (lazy[p][k]) down(k);
    int mid=L[k]+R[k]>>1;
    if (r<=mid) return getsame(k<<1,l,r,p);
    else if (l>mid) return getsame(k<<1|1,l,r,p);
    else return getsame(k<<1,l,mid,p)&getsame(k<<1|1,mid+1,r,p);
}
int query1(int k,int l,int r,int p)
{
    if (L[k]==R[k]) return same[p][k]?l:0;
    if (lazy[p][k]) down(k);
    int mid=L[k]+R[k]>>1;
    if (r<=mid) return query1(k<<1,l,r,p);
    else if (l>mid) return query1(k<<1|1,l,r,p);
    else return getsame(k,mid,r,p)?query1(k<<1,l,mid,p):query1(k<<1|1,mid+1,r,p);
}
int queryance(int x,int p)
{
    int ans=id[x];
    while (1)
    {
        int y=query1(1,id[top[x]],id[x],p);
        if (!y) break;
        if (y>id[top[x]]) return y;
        ans=id[top[x]];
        if (x==1) break;
        x=fa[top[x]];
    }
    return ans;
}
int query(int k,int x,int p)
{
    if (L[k]==R[k]) return tree[p][k];
    if (lazy[p][k]) down(k);
    int mid=L[k]+R[k]>>1;
    if (x<=mid) return query(k<<1,x,p);
    else return query(k<<1|1,x,p);
}
void modify(int k,int l,int r,int x,int p)
{
    if (L[k]==l&&R[k]==r) {tree[p][k]+=x,lazy[p][k]+=x;return;}
    if (lazy[p][k]) down(k);
    int mid=L[k]+R[k]>>1;
    if (r<=mid) modify(k<<1,l,r,x,p);
    else if (l>mid) modify(k<<1|1,l,r,x,p);
    else modify(k<<1,l,mid,x,p),modify(k<<1|1,mid+1,r,x,p);
}
void modifycolor(int k,int x,int p,int op)
{
    if (L[k]==R[k]) {same[p][k]=op;return;}
    int mid=L[k]+R[k]>>1;
    if (x<=mid) modifycolor(k<<1,x,p,op);
    else modifycolor(k<<1|1,x,p,op);
    same[p][k]=same[p][k<<1]&&same[p][k<<1|1];
}
void modifyance(int x,int p,int s,int y)
{
    while (top[x]!=top[y])
    {
        modify(1,id[top[x]],id[x],s,p);
        x=fa[top[x]];
    }
    modify(1,id[y],id[x],s,p);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("bzoj3637.in","r",stdin);
    freopen("bzoj3637.out","w",stdout);
    const char LL[]="%I64d\n";
#else
    const char LL[]="%lld\n";
#endif
    n=read();
    for (int i=1;i<n;i++)
    {
        int x=read(),y=read();
        addedge(x,y),addedge(y,x);
    }
    fa[1]=1;dfs1(1);
    dfs2(1,1);
    build(1,1,n);
    m=read();
    while (m--)
    {
        int op=read(),x=read(),y=queryance(x,color[x]);
        if (op)
        {
            if (id[x]==y)
            {
                modifycolor(1,id[x],color[x],0);
                color[x]^=1;
                modifycolor(1,id[x],color[x],1);
                y=queryance(x,color[x]);
                if (x>1)
                modifyance(fa[x],color[x],query(1,id[x],color[x]),fa[dfn[y]]),
                modify(1,id[fa[x]],id[fa[x]],-query(1,id[x],color[x]^1),color[x]^1);
            }
            else
            {
                if (x>1)
                modifyance(fa[x],color[x],-query(1,id[x],color[x]),fa[dfn[y]]),
                modify(1,id[fa[x]],id[fa[x]],query(1,id[x],color[x]^1),color[x]^1);
                modifycolor(1,id[x],color[x],0);
                color[x]^=1;
                modifycolor(1,id[x],color[x],1);
            }
        }
        else printf("%d\n",query(1,y,color[x]));
    }
    return 0;
}    

猜你喜欢

转载自www.cnblogs.com/Gloid/p/9720385.html