• BZOJ 3720 gty的妹子树


    块状树裸题

    块状树:

    首先对树进行分块,分出的每一块都是一个连通块

    通常的分块的方式如下:

    1、父亲所在块不满,分到父亲所在块中

    2、父亲所在块满,自己单独开一个块

    (貌似有更为优越的分块方式?

    注意这是不严格的分块,即每个块的大小不一定都是设定的阈值blo

    对于这道题,首先修改和添加直接块内暴力就可以了

    对于询问,首先我们对每个块排序,块不完全在询问子树内的单点询问,块完全在询问子树内的块内二分

    分块真是骗分利器,但是块状树最大的缺点是容易被菊花树卡住

    (貌似修改和添加可以去掉一个log,但是我太弱了,并不想写)

    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #include<cmath> 
    using namespace std;
     
    const int oo=0x7fffffff;
    const int maxn=200010;
    int n,m,u,v,f,ans,tot,blo;
    int pos[maxn],fa[maxn],w[maxn];
    int a[10010][510],cnt[10010];
    struct Graph{
        int h[maxn],next[maxn],to[maxn],sum;
        void add(int x,int y){++sum;next[sum]=h[x];h[x]=sum;to[sum]=y;}
    }G,T;
    void read(int &num){
        num=0;char ch=getchar();
        while(ch<'!')ch=getchar();
        while(ch>='0'&&ch<='9')num=num*10+ch-'0',ch=getchar();
    }
    bool cmp(const int &i,const int &j){return i>j;}
    void check_block(int u){
        int k=pos[fa[u]];
        if(cnt[k]==blo){
            pos[u]=++tot;a[tot][0]=oo;
            a[tot][++cnt[tot]]=w[u];
            T.add(k,tot);
        }else a[k][++cnt[k]]=w[u],pos[u]=k;
        for(int i=G.h[u];i;i=G.next[i]){
            if(G.to[i]==fa[u])continue;
            fa[G.to[i]]=u;
            check_block(G.to[i]);
        }return;
    }
    int Get_pos(int u){
        int L=0,R=cnt[u];
        while(L<R){
            int mid=L+((R-L+1)>>1);
            if(a[u][mid]>v)L=mid;
            else R=mid-1;
        }return L;
    }
    void Get_block(int u){
        ans+=Get_pos(u);
        for(int i=T.h[u];i;i=T.next[i])Get_block(T.to[i]);
    }
    void Get_ask(int u){
        if(w[u]>v)ans++;
        for(int i=G.h[u];i;i=G.next[i]){
            if(G.to[i]==fa[u])continue;
            if(pos[G.to[i]]==pos[u])Get_ask(G.to[i]);
            else Get_block(pos[G.to[i]]);
        }return;
    }
    void Get_insert(int u,int k){
        pos[u]=k;w[u]=v;a[k][++cnt[k]]=v;
        sort(a[k]+1,a[k]+cnt[k]+1,cmp);
    }
    void Get_modify(int u){
        int k=pos[u];
        for(int i=1;i<=cnt[k];++i){
            if(a[k][i]==w[u]){a[k][i]=v;break;}
        }
        w[u]=v;
        sort(a[k]+1,a[k]+cnt[k]+1,cmp);
    }
     
    int main(){
        read(n);
        for(int i=1;i<n;++i){
            read(u);read(v);
            G.add(u,v);G.add(v,u);
        }
        for(int i=1;i<=n;++i)read(w[i]);
        blo=(int)(sqrt(n));
        fa[1]=1;pos[1]=1;tot=1;
        check_block(1);
        for(int i=1;i<=tot;++i)sort(a[i]+1,a[i]+cnt[i]+1,cmp);
        //for(int i=1;i<=n;++i)cout<<pos[i]<<endl;
        //cout<<endl;
        read(m);
        while(m--){
            read(f);read(u);read(v);
            u^=ans;v^=ans;
            if(f==0){
                ans=0;
                Get_ask(u);
                printf("%d
    ",ans);
            }else if(f==2){
                n++;fa[n]=u;G.add(u,n);
                if(cnt[pos[u]]==blo){
                    pos[n]=++tot;w[n]=v;a[tot][0]=oo;
                    a[tot][++cnt[tot]]=w[n];
                    T.add(pos[u],tot);
                }else Get_insert(n,pos[u]);
            }else Get_modify(u);
        }return 0;
    }
    gty的妹子树
  • 相关阅读:
    LPTHW 笨办法学python 20章
    LPTHW 笨方法学python 19章
    LPTHW 笨方法学python 18章
    LPTHW 笨方法学习python 16章
    hadoop删除节点。
    url中的百分号转译
    thrift编译安装
    python学习:函数的学习
    jsp静态导入和动态导入 笔记
    简要描述cookie和session的区别:
  • 原文地址:https://www.cnblogs.com/joyouth/p/5333238.html
Copyright © 2020-2023  润新知