bzoj 3720: Gty的妹子树

Description

我曾在弦歌之中听过你,
檀板声碎,半出折子戏。
舞榭歌台被风吹去,
岁月深处尚有余音一缕……
Gty神(xian)犇(chong)从来不缺妹子……
他来到了一棵妹子树下,发现每个妹子有一个美丽度……
由于Gty很哲♂学,他只对美丽度大于某个值的妹子感兴趣。
他想知道某个子树中美丽度大于k的妹子个数。
某个妹子的美丽度可能发生变化……
树上可能会出现一只新的妹子……
维护一棵初始有n个节点的有根树(根节点为1),树上节点编号为1-n,每个点有一个权值wi。
支持以下操作:
0 u x 询问以u为根的子树中,严格大于x的值的个数。(u=lastans,x=lastans)
1 u x 把u节点的权值改成x。(u=lastans,x=lastans)
2 u x 添加一个编号为"当前树中节点数+1"的节点,其父节点为u,其权值为x。(u=lastans,x=lastans)
最开始时lastans=0。

解题报告

对于这个题,直接以父亲所在块的\(size\)分块,如果父亲节点\(size<B\),直接把当前节点加入块中,否则新建一个块,\(B\)为设定的块的大小,对于插入做相同的判断即可.我们维护一个块内的节点的权值的单调性,每一次询问相同块内暴力找,如果遍历到了其他块直接二分块内即可,对于块与块之间可以建一个新图,方便遍历使用.
对于修改操作,我们可以直接修改后sort,也可以利用单调性\(O(B)\)插入,推荐后面一种方法.
另外就是块大小的设定:本题中最优设定为 \(\sqrt{n*log}\),可以简单证明:插入为\(O(B)\),询问为 \(O(n*log(B)/B)\),总复杂度为 \(B+nlog(B)/B\),根据均值不等式 \(B\)\(\sqrt{n*log}\)最优

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=70005,B=631;
int n,fa[N],val[N],num=0,head[N],cnt=0,bel[N],Head[N],NUM=0,ans=0;
struct edge{int nxt,to;}a[N<<1],e[N<<1];
il void link(int x,int y){a[++num].nxt=head[x];a[num].to=y;head[x]=num;}
il void lenk(int x,int y){e[++NUM].nxt=Head[x];e[NUM].to=y;Head[x]=NUM;}
struct block{
    int c[B+5],size;
    il void insert(int x){
        size++;RG int i=size;
        for(i=size;i>=2 && x<=c[i-1];i--)c[i]=c[i-1];
        c[i]=x;
    }
    il void upd(int x,int y){
        RG int p=lower_bound(c+1,c+size+1,x)-c,i;
        for(i=p;i<size;i++)c[i]=c[i+1];
        for(i=size;i>=2 && y<=c[i-1];i--)c[i]=c[i-1];
        c[i]=y;
    }
    il int query(int x){
        int i=upper_bound(c+1,c+size+1,x)-c;
        return size-i+1;
    }
}b[6005];
il void dfs(RG int x){
    if(b[bel[fa[x]]].size<B)bel[x]=bel[fa[x]],b[bel[x]].insert(val[x]);
    else bel[x]=++cnt,b[cnt].insert(val[x]),lenk(bel[fa[x]],cnt);
    for(RG int i=head[x],u;i;i=a[i].nxt){
        u=a[i].to;if(u==fa[x])continue;
        fa[u]=x;dfs(u);
    }
}
il void btree(int x,int y){
    ans+=b[x].query(y);
    for(int i=Head[x],u;i;i=e[i].nxt){
        u=e[i].to;btree(u,y);
    }
}
il void qtree(int x,int y){
    if(val[x]>y)ans++;
    for(RG int i=head[x],u;i;i=a[i].nxt){
        u=a[i].to;if(u==fa[x])continue;
        if(bel[u]==bel[x])qtree(u,y);
        else btree(bel[u],y);
    }
}
void work()
{
    int x,y;
    scanf("%d",&n);
    for(RG int i=1;i<n;i++){
        scanf("%d%d",&x,&y);
        link(x,y);link(y,x);
    }
    for(RG int i=1;i<=n;i++)scanf("%d",&val[i]);
    dfs(1);
    int m,flag;scanf("%d",&m);
    while(m--){
        scanf("%d%d%d",&flag,&x,&y);
        x^=ans;y^=ans;
        if(flag==0)ans=0,qtree(x,y),printf("%d\n",ans);
        else if(flag==1){
            b[bel[x]].upd(val[x],y);
            val[x]=y;
        }
        else{
            fa[++n]=x;val[n]=y;link(x,n);link(n,x);
            if(b[bel[x]].size<B)bel[n]=bel[x],b[bel[x]].insert(y);
            else bel[n]=++cnt,lenk(bel[x],cnt),b[cnt].insert(y);
        }
    }
}

int main()
{
    work();
    return 0;
}

posted @ 2017-10-12 08:27  PIPIBoss  阅读(159)  评论(0编辑  收藏  举报