码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 3731 Gty的超级妹子树 块状树

时间:2014-11-26 14:20:04      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:bzoj   bzoj3731   块状树   树分块   

题目大意:同3720 增加了一个操作 即删除一个点与父亲节点的连边

3720题解见 http://blog.csdn.net/popoqqq/article/details/41481439

断开一个节点与父节点的连边时

如果这个点是所在块的根节点,直接断掉就行

如果这个点不是所在块的根节点,那么就要把这个块分裂,这个点以及在块中的子树都分裂到新的块中,细节讨论较多不大好写0.0

然后是一些小问题

1.此题卡内存 静态不用想了 开vector吧

2.是我常数写渣了还是这题真的卡时间0.0 之前是把块先清空然后再往里加 T到死…… 没办法了改成分裂出的点从原块中删除 然后再加进新的块中 然后加了一堆优化QAQ

#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define M 100100
#define Block_Size 200200
using namespace std;
namespace IOStream{
    const int L=1<<15;
    char buffer[L];
    char *S,*T;
    char Get_Char()
    {
        if(S==T)
        {
            T=(S=buffer)+fread(buffer,1,L,stdin);
            if(S==T)
                return EOF;
        }
        return *S++;
    }
    int Get_Int()
    {
        int re=0;
        char c;
        do c=Get_Char(); while(c<'0'||c>'9');
        while(c>='0'&&c<='9')
            re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();
        return re;
    }
}
struct Block{
    vector<int>a;
    void Insert(int x)
    {
        a.insert( lower_bound(a.begin(),a.end(),x+1) , x );
    }
    void Delete(int x)
    {
        a.erase( lower_bound(a.begin(),a.end(),x) );
    }
    void Modify(int x,int y)
    {
        Delete(x);
        Insert(y);
    }
    int Query(int x)
    {
        int temp=upper_bound(a.begin(),a.end(),x)-a.begin()+1;
        return a.size()-temp+1;
    }
}blocks[Block_Size];
struct abcd{
    int to,next;
    bool ban;
}table[M*3];
int head[M<<1],block_head[Block_Size],tot;
int n,m,block,ans,cnt;
int a[M<<1],fa[M<<1],belong[M<<1],into[M],block_into[Block_Size];
void Add(int _head[],int x,int y)
{
    table[++tot].to=y;
    table[tot].next=_head[x];
    _head[x]=tot;
    if(_head==head)
        into[y]=tot;
    else
        block_into[y]=tot;
}
void DFS(int x)
{
    int i;
    if(!fa[x]||blocks[belong[fa[x]]].a.size()>=block)
        blocks[belong[x]=++cnt].Insert(a[x]),Add(block_head,belong[fa[x]],cnt);
    else
        blocks[belong[x]=belong[fa[x]]].Insert(a[x]);
    for(i=head[x];i;i=table[i].next)
    {
        if(table[i].to==fa[x])
        {
            table[i].ban=1;
            continue;
        }
        fa[table[i].to]=x,DFS(table[i].to);
    }
}
void Block_DFS(int x,int y)
{
    int i;
    ans+=blocks[x].Query(y);
    for(i=block_head[x];i;i=table[i].next)
        if(!table[i].ban)
            Block_DFS(table[i].to,y);
}
void DFS(int x,int y)
{
    int i;
    if(a[x]>y) ++ans; 
    for(i=head[x];i;i=table[i].next)
        if(!table[i].ban)
            if(belong[table[i].to]==belong[x])
                DFS(table[i].to,y);
            else
                Block_DFS(belong[table[i].to],y);
}
void DFS2(int x)
{
    int i;
    for(i=head[x];i;i=table[i].next)
        if(!table[i].ban)
            into[table[i].to]=i,DFS2(table[i].to);  
}
void Decomposition(int x,bool flag,int neo,int z,int ori)
{
    int i;
    if(x==z) flag=1;
    //blocks[belong[x]=(flag?neo:ori)].Insert(a[x]);
    if(flag)
    {
        blocks[ori].Delete(a[x]);
        blocks[belong[x]=neo].Insert(a[x]);
    }
    for(i=head[x];i;i=table[i].next)
        if(!table[i].ban)
        {
            if(belong[table[i].to]==ori)
                Decomposition(table[i].to,flag,neo,z,ori);
            else if(flag)
                table[block_into[belong[table[i].to]]].ban=1,Add(block_head,neo,belong[table[i].to]);
        }
}
int main()
{
     
    //#ifdef C_PoPoQQQ
    //freopen("data.in","r",stdin);
    //freopen("data.out","w",stdout);
    //#endif
     
    int i,j,x,y,p;
    cin>>n;
    for(i=1;i<n;i++)
        Add(head,x=IOStream::Get_Int(),y=IOStream::Get_Int() ),Add(head,y,x);
    for(i=1;i<=n;i++)
        a[i]=IOStream::Get_Int();
    block=static_cast<int>(sqrt(n*log2(n))+1e-7);
    DFS(1);
    DFS2(1);
    m=IOStream::Get_Int();
    for(i=1;i<=m;i++)
    {
        #ifdef C_PoPoQQQ
        //ans=0;
        #endif
        p=IOStream::Get_Int();
        switch(p)
        {
            case 0:
                x=IOStream::Get_Int()^ans,y=IOStream::Get_Int()^ans;
                ans=0;
                DFS(x,y);
                printf("%d\n",ans);
                break;
            case 1:
                x=IOStream::Get_Int()^ans,y=IOStream::Get_Int()^ans;
                blocks[belong[x]].Modify(a[x],y);
                a[x]=y;
                break;
            case 2:
                x=IOStream::Get_Int()^ans,y=IOStream::Get_Int()^ans;
                a[++n]=y;
                Add(head,x,n);
                fa[n]=x;
                if(blocks[belong[x]].a.size()==block)
                    blocks[belong[n]=++cnt].Insert(y),Add(block_head,belong[x],cnt);
                else
                    blocks[belong[n]=belong[x]].Insert(y);
                break;
            case 3:
                x=IOStream::Get_Int()^ans;
                if(belong[fa[x]]!=belong[x])
                    table[block_into[belong[x]]].ban=1;
                else
                {
                    for(y=x;fa[y]&&belong[fa[y]]==belong[x];y=fa[y]);
                    //blocks[belong[x]].a.clear();
                    Decomposition(y,0,++cnt,x,belong[x]);
                }
                table[into[x]].ban=1;
                fa[x]=0;
                break;
        }
    }
    return 0;
}


BZOJ 3731 Gty的超级妹子树 块状树

标签:bzoj   bzoj3731   块状树   树分块   

原文地址:http://blog.csdn.net/popoqqq/article/details/41514807

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!