zoukankan      html  css  js  c++  java
  • [bzoj3720]Gty的妹子树

     来自FallDream的博客,未经允许,请勿转载,谢谢。


    题意:给你一棵树,有点权,要求支持三个操作:1)单点修改 2)插入一个点 3)询问子树内权值大于一个数的节点个数。

    n,m<=30000

    去网上搜了一下,发现大家都是块状树啊,还有像带插区间k大那样的替罪羊套treap之类的。但是我写了一个很奇怪的做法 

    首先很容易想到主席树之类的,建一次主席树是nlogn的

    然后我们把修改操作全部压到一个栈里面,询问的时候把栈遍历一遍计算答案;每当操作到达一定数量的时候,重建整棵树。

    假设操作到达k之后重建,复杂度是$O(frac{n}{k}*nlogn+m(k+logn))$ 

    k取到大约$sqrt{nlogn}$的时候复杂度最小  灰常科学啊

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #define MN 60000
    #define INF 2147483647
    #define ll long long
    using namespace std;
    inline int read()
    {
        int x = 0 , f = 1; char ch = getchar();
        while(ch < '0' || ch > '9'){ if(ch == '-') f = -1;  ch = getchar();}
        while(ch >= '0' && ch <= '9'){x = x * 10 + ch - '0';ch = getchar();}
        return x * f;
    }
    struct edge{int to,next;}e[MN*2+5];
    struct Tree{int l,r,x;}T[5000000];
    struct operation{int kind,x,y,z;}q[MN+5];
    int cnt,n,en=0,head[MN+5],last=0,top,nl[MN+5],nr[MN+5],dn=0,m,sz,p[MN+5],a[MN+5],rt[MN+5];
    bool b[MN+5];
    
    void ins(int f,int t)
    {
        e[++en]=(edge){t,head[f]};head[f]=en;
        e[++en]=(edge){f,head[t]};head[t]=en;
    }
    
    void dfs(int x,int f)
    {
        p[nl[x]=++dn]=x;
        for(int i=head[x];i;i=e[i].next)
            if(e[i].to!=f) dfs(e[i].to,x);
        nr[x]=dn;
    }
    
    void ins(int x,int nx,int k)
    {
        int l=0,r=INF,mid;
        while(l<r)
        {
            mid=((ll)l+r)>>1;
            if(k<=mid)
            {
                T[nx].r=T[x].r;T[nx].l=++cnt;
                r=mid;x=T[x].l;nx=T[nx].l;
            }
            else
            {
                T[nx].l=T[x].l;T[nx].r=++cnt;
                l=mid+1;x=T[x].r;nx=T[nx].r;
            }
            T[nx].x=T[x].x+1;
        }
    }
    
    int query(int x,int nx,int k)
    {
        int sum=0,l=0,r=INF,mid;
        while(l<r)
        {
            mid=((ll)l+r)>>1;
            if(k>mid) x=T[x].r,nx=T[nx].r,l=mid+1;
            else sum+=T[T[nx].r].x-T[T[x].r].x,r=mid,x=T[x].l,nx=T[nx].l;
        }
        return sum+T[nx].x-T[x].x;
    }
    
    void build()
    {
        dn=cnt=0;dfs(1,0);
        for(int i=1;i<=n;i++)
            ins(rt[i-1],rt[i]=++cnt,a[p[i]]);    
    }
    
    int main()
    {
        n=read();sz=sqrt(15*n);
        for(int i=1;i<n;i++) ins(read(),read());
        for(int i=1;i<=n;i++) a[i]=read();
        build();m=read();
        for(int i=1,ad=0;i<=m;i++)
        {
            int op=read(),x=read()^last,y=read()^last;
            if(op==0)
            {
                if(x<=n)
                {
                    int ans=(y==INF?0:query(rt[nl[x]-1],rt[nr[x]],y+1));
                    for(int j=1;j<=top;j++)
                        if(q[j].kind==1)
                        {
                            if(q[j].x<=n&&nl[q[j].x]>=nl[x]&&nl[q[j].x]<=nr[x])
                                ans=ans-(q[j].y>y)+(q[j].z>y);    
                        }
                        else
                        {
                            if((b[q[j].y]&&q[j].y>n)||(q[j].y<=n&&nl[q[j].y]>=nl[x]&&nl[q[j].y]<=nr[x])) b[q[j].x]=1;
                            else b[q[j].x]=0;
                        }
                    for(int j=1;j<=ad;j++)
                        if(b[n+j]) ans+=(a[n+j]>y); 
                    printf("%d
    ",last=ans);
                }
                else
                {
                    int ans=0;
                    for(int j=1;j<=top;j++)
                        if(q[j].kind==2)
                        {
                            if((b[q[j].y]&&q[j].y>n)||q[j].x==x) b[q[j].x]=1;
                            else b[q[j].x]=0;    
                        } 
                    for(int j=1;j<=ad;j++)
                        if(b[n+j]) ans+=(a[n+j]>y);
                    printf("%d
    ",last=ans);
                }
            }
            else if(op==1) 
                q[++top]=(operation){1,x,a[x],y},a[x]=y;
            else
                q[++top]=(operation){2,n+(++ad),x,0},ins(n+ad,x),a[n+ad]=y;
            if(top>=sz) n+=ad,top=0,ad=0,build();
        }
        return 0;
    }
  • 相关阅读:
    Android自定义之仿360Root大师水纹效果
    Android之TextView的Span样式源码剖析
    Android之TextView的样式类Span的使用详解
    随着ScrollView的滑动,渐渐的执行动画View
    仿微信主界面导航栏图标字体颜色的变化
    android自定义之 5.0 风格progressBar
    Android性能优化之内存篇
    Android性能优化之运算篇
    How to install Zabbix5.0 LTS version with Yum on the CentOS 7.8 system?
    How to install Zabbix4.0 LTS version with Yum on the Oracle Linux 7.3 system?
  • 原文地址:https://www.cnblogs.com/FallDream/p/bzoj3720.html
Copyright © 2011-2022 走看看