题目大意:同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;
}