记录编号 |
444162 |
评测结果 |
AAAAAAAAAAAAAAAAAAAA |
题目名称 |
[SYZOI Round1]滑稽♂树 |
最终得分 |
100 |
用户昵称 |
wumingshi |
是否通过 |
通过 |
代码语言 |
C++ |
运行时间 |
2.935 s |
提交时间 |
2017-09-02 11:04:16 |
内存使用 |
44.54 MiB |
显示代码纯文本
#include<cstdio>
const int N=2e5+10;
struct node
{
int num,size,cnt;
node *ch[2],*fa;
inline int getwh(){return fa->ch[0]==this?0:1;}
inline void update(){size=ch[0]->size+ch[1]->size+cnt;}
inline void setch(int wh,node *child);
}pool[1500000],*t[N<<2],*null;
inline void node::setch(int wh,node *child)
{
ch[wh]=child;
if(child!=null) child->fa=this;
update();
}
struct edge
{
int nxt,to;
}e[N<<1];
int head[N],a[N],size[N],pos[N],s[N];
int n,m,opt,x,y,z,tot,cnt,num;
inline void add(int x,int y)
{
e[++num].nxt=head[x],e[num].to=y,head[x]=num;
e[++num].nxt=head[y],e[num].to=x,head[y]=num;
}
void dfs(int now,int fa)
{
size[now]=1,pos[now]=++cnt;s[cnt]=a[now];
for(int i=head[now];i;i=e[i].nxt)
if(e[i].to!=fa) dfs(e[i].to,now),size[now]+=size[e[i].to];
}
inline node *getnew(int value,bool normal)
{
node *now=pool+ ++tot;
now->ch[0]=now->ch[1]=now->fa=null;
if(normal) now->size=now->cnt=1;
now->num=value;
return now;
}
inline void rotate(node *now)
{
node *fa=now->fa,*grand=fa->fa;
int wh=now->getwh();
fa->setch(wh,now->ch[wh^1]);
now->setch(wh^1,fa);
now->fa=grand;
if(grand!=null) grand->ch[grand->ch[0]==fa?0:1]=now;
fa->update(),now->update(),grand->update();
}
inline void splay(node *now,node *tar,node *&root)
{
for(;now->fa!=tar;rotate(now))
if(now->fa->fa!=tar) now->getwh()==now->fa->getwh()?rotate(now->fa):rotate(now);
if(tar==null) root=now;
}
inline void insert(int value,node *&root,bool normal)
{
node *now=root,*last=null;
while(now!=null)
{
last=now;
if(now->num==value){now->cnt++,now->size++,splay(now,null,root);return;}
if(now->num>value) now=now->ch[0];
else now=now->ch[1];
}
if(last==null){root=getnew(value,normal);return;}
now=getnew(value,normal);
if(last->num>value) last->setch(0,now);
else last->setch(1,now);
splay(now,null,root);
}
inline node *find(int value,node *&root)
{
node *now=root;
while(now!=null)
{
if(now->num==value){splay(now,null,root);return now;}
if(now->num>value) now=now->ch[0];
else now=now->ch[1];
}
}
inline void del(int value,node *&root)
{
node *now=find(value,root);
if(now->cnt>1){now->cnt--,now->size--,splay(now,null,root);return;}
if(now->ch[0]==null&&now->ch[1]==null){root=null;return;}
if(now->ch[0]==null){root=now->ch[1],root->fa=null;return;}
if(now->ch[1]==null){root=now->ch[0],root->fa=null;return;}
node *Root=now->ch[0];
while(Root->ch[1]!=null) Root=Root->ch[1];
splay(Root,now,root);
Root->setch(1,now->ch[1]);
Root->fa=null;
root=Root;
}
inline int rank(int value,node *&root)
{
int ans=0;node *now=root;
while(now!=null)
{
if(now->num==value){ans+=now->ch[0]->size;splay(now,null,root);return ans;}
if(now->num>value) now=now->ch[0];
else ans+=now->ch[0]->size+now->cnt,now=now->ch[1];
}
return ans;
}
inline node *pre(int value,node *&root)
{
node *now=root,*ans=null;
while(now!=null)
if(now->num<value) ans=now,now=now->ch[1];
else now=now->ch[0];
return ans;
}
inline node *nxt(int value,node *&root)
{
node *now=root,*ans=null;
while(now!=null)
if(now->num>value) ans=now,now=now->ch[0];
else now=now->ch[1];
return ans;
}
inline int ask(int l,int r,node *&root)
{
splay(pre(l,root),null,root);
splay(nxt(r,root),root,root);
return root->ch[1]->ch[0]->size;
}
inline void init(int l,int r,node *&root)
{
root=null;
insert(-1,root,0),insert(20000,root,0);
for(int i=l;i<=r;i++)
insert(s[i],root,1);
}
void build(int l,int r,int now)
{
init(l,r,t[now]);
if(l==r) return;
int mid=(l+r)>>1;
build(l,mid,now<<1);
build(mid+1,r,now<<1|1);
}
void change(int p,int l,int r,int now,int num)
{
del(s[p],t[now]),insert(num,t[now],1);
if(l==r) return;
int mid=(l+r)>>1;
if(p<=mid) change(p,l,mid,now<<1,num);
else change(p,mid+1,r,now<<1|1,num);
}
int askrank(int L,int R,int l,int r,int now,int num)
{
if(L<=l&&r<=R) return rank(num,t[now]);
int mid=(l+r)>>1,ans=0;
if(L<=mid) ans=askrank(L,R,l,mid,now<<1,num);
if(R>mid) ans+=askrank(L,R,mid+1,r,now<<1|1,num);
return ans;
}
inline int Rank(int l,int r,int num)
{
int L=0,R=10001;
while(L<R)
{
int mid=(L+R)>>1;
if(askrank(l,r,1,n,1,mid)<num) L=mid+1;
else R=mid;
}
return L-1;
}
inline int askval(int L,int R,int l,int r,int now,int x,int y)
{
if(L<=l&&r<=R) return ask(x,y,t[now]);
int mid=(l+r)>>1,ans=0;
if(L<=mid) ans=askval(L,R,l,mid,now<<1,x,y);
if(R>mid) ans+=askval(L,R,mid+1,r,now<<1|1,x,y);
return ans;
}
int main()
{
freopen("hjtree.in","r",stdin);
freopen("hjtree.out","w",stdout);
null=pool;
null->ch[0]=null->ch[1]=null;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<n;i++)
scanf("%d%d",&x,&y),add(x,y);
dfs(1,0);build(1,n,1);
scanf("%d",&m);int tmp=0;
while(m--)
{
tmp++;
scanf("%d%d%d",&opt,&x,&y);
if(opt==1) printf("%d\n",Rank(pos[x],pos[x]+size[x]-1,y));
else if(opt==2) scanf("%d",&z),printf("%d\n",askval(pos[x],pos[x]+size[x]-1,1,n,1,y,z));
else change(pos[x],1,n,1,y),s[pos[x]]=y;
}
return 0;
}