• Gty的妹子树(bzoj 3720)


    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。

    Input

    输入第一行包括一个正整数n(1<=n<=30000),代表树上的初始节点数。

    接下来n-1行,每行2个整数u,v,为树上的一条无向边。

    任何时刻,树上的任何权值大于等于0,且两两不同。

    接下来1行,包括n个整数wi,表示初始时每个节点的权值。

    接下来1行,包括1个整数m(1<=m<=30000),表示操作总数。

    接下来m行,每行包括三个整数 op,u,v:

    op,u,v的含义见题目描述。

    保证题目涉及的所有数在int内。

    Output

    对每个op=0,输出一行,包括一个整数,意义见题目描述。

    Sample Input

    2
    1 2
    10 20
    1
    0 1 5

    Sample Output

    2
    /*
      刚开始打算在dfs序上搞事情,然后发现不会动态维护,所以只能树上分块。
      先搞出一个块长len,在dfs时,超过这个len就重新划分一块,维护块之间的连通性。
      添加的时候可以超过len就更新一块新的,但是由于懒的写,所以直接添加的,导致跑到了10000+。 
    */
    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<cmath>
    #define N 60010
    using namespace std;
    int w[N],head[N],fa[N],dep[N],bl[N],size[N],ind[N],vis[N],n,m,cnt,len;
    struct node{int v,pre;}e[N*2];
    vector<int> g[N],blo[N];
    void add(int u,int v){
        e[++cnt].v=v;
        e[cnt].pre=head[u];
        head[u]=cnt;
    }
    void dfs(int x){
        for(int i=head[x];i;i=e[i].pre){
            if(e[i].v==fa[x]) continue;
            fa[e[i].v]=x;dep[e[i].v]=dep[x]+1;
            if(size[x]<len) size[bl[e[i].v]=bl[x]]++;
            else {
                g[bl[x]].push_back(bl[e[i].v]);
                g[bl[e[i].v]].push_back(bl[x]);
            }
            dfs(e[i].v);
        }
    }
    int query(int x,int y){
        int ans=0;
        if(bl[x]==x){
            ans+=blo[x].end()-upper_bound(blo[x].begin(),blo[x].end(),y);
            for(int i=0;i<g[bl[x]].size();i++){
                int v=g[bl[x]][i];
                if(dep[v]<dep[x]) continue;
                ans+=query(v,y);
            }
            return ans;
        }
        else {
            ans+=w[x]>y;
            for(int i=head[x];i;i=e[i].pre){
                if(fa[x]==e[i].v) continue;
                ans+=query(e[i].v,y);
            }
            return ans;
        }
    }
    void modify(int x,int y){
        int pos=lower_bound(blo[bl[x]].begin(),blo[bl[x]].end(),w[x])-blo[bl[x]].begin();
        w[x]=y;blo[bl[x]][pos]=y;
        sort(blo[bl[x]].begin(),blo[bl[x]].end());
    }
    void join(int x,int y){
        fa[++n]=x;w[n]=y;dep[n]=dep[x]+1;
        add(x,n);add(n,x);
        blo[bl[n]=bl[x]].push_back(y);
        sort(blo[bl[x]].begin(),blo[bl[x]].end());
    }
    int main(){
        scanf("%d",&n);
        //len=sqrt((double)n/log((double)n)*log(2));
        len=sqrt(n);
        for(int i=1;i<n;i++){
            int u,v;scanf("%d%d",&u,&v);
            add(u,v);add(v,u);
        }
        for(int i=1;i<=n;i++)
            scanf("%d",&w[i]),size[i]=1,bl[i]=i;
        dfs(1);
        for(int i=1;i<=n;i++){
            blo[bl[i]].push_back(w[i]);
            if(!vis[bl[i]])vis[bl[i]]=1,ind[++ind[0]]=bl[i];
        }
        for(int i=1;i<=ind[0];i++)
            sort(blo[ind[i]].begin(),blo[ind[i]].end());
        scanf("%d",&m);int ans=0;
        for(int i=1;i<=m;i++){
            int opt,x,y;scanf("%d%d%d",&opt,&x,&y);
            x^=ans;y^=ans;
            if(opt==0) ans=query(x,y),printf("%d
    ",ans);
            else if(opt==1) modify(x,y);
            else join(x,y);
        }
        return 0;
    }
  • 相关阅读:
    关于HashMap的线程安全问题
    Java利器之UML类图详解
    mongoDB4.0数据库
    requests-html库render的使用
    爬虫最新的库requests-html库总结
    爬虫多次爬取时候cookie的存储用于登入
    requests模块响应体属性和方法重新整理
    Visual Studio 代码补全功能有时候会失效的原因
    C++Primer笔记——文本查询程序(原创,未使用类)
    Clion 常用快捷键
  • 原文地址:https://www.cnblogs.com/harden/p/6435730.html
Copyright © 2020-2023  润新知