• 牛客练习赛42 E.热爆了


    这可能是全场最长的一份代码

    问的其实是对于关键点的斯坦纳树大小

    考虑补集转化,不合法的点就是它的子树中没有关键点的点和斯坦纳树根的祖先

    树根不难求,关键点中dfs序最大最小点的LCA就是了

    问题在前者

    假如我们把子树中的点拿出来排序,这个点不合法的条件就是存在ax,ax+1满足ax<=l-1且r+1<=ax+1,有个很妙的性质就是这个合法的x只有1个

    考虑启发式合并把这个顺序搞出来,可以证明点数是nlogn级别的,因为每次合并均摊加入logn个点,合并n次。数列相邻的两项成为一个点,插入要用到一棵splay来维护一下。。。

    把这些点放到二维平面二维数点即可。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int _=1e2;
    const int maxn=1e5+_;
    const int maxQ=5e5+_;
    const int mbit=30;
    const int fbin=(1<<17)+_;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    int n,Q;
    struct node
    {
        int x,y,next;
    }a[2*maxn];int len,last[maxn],d[maxn];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    
    //--------------------------------------------def-------------------------------------------------------
    
    namespace TREE
    {
        namespace Segtree
        {
            struct segtree{int mx,mn;segtree(){mn=(1<<30);}}tr[2*fbin];
            void update(int now)
            {
                int lc=(now<<1),rc=(now<<1|1);
                tr[now].mx=max(tr[lc].mx,tr[rc].mx);
                tr[now].mn=min(tr[lc].mn,tr[rc].mn);
            }
            void pushdown(int now)
            {
                int lc=(now<<1),rc=(now<<1|1);
                tr[lc].mx=max(tr[now].mx,tr[lc].mx);
                tr[rc].mn=min(tr[now].mn,tr[rc].mn);
            }
            void change(int now,int ql,int qr,int p,int k)
            {
                if(ql==qr)
                {
                    tr[now].mx=max(tr[now].mx,k);
                    tr[now].mn=min(tr[now].mn,k);
                    return ;
                }
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                if(p<=mid)change(lc,ql,mid,p,k);
                else change(rc,mid+1,qr,p,k);
                update(now);
            }
            int getmax(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r)return tr[now].mx;
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                     if(r<=mid)  return getmax(lc,ql,mid,l,r);
                else if(mid+1<=l)return getmax(rc,mid+1,qr,l,r);
                else return max(getmax(lc,ql,mid,l,mid),getmax(rc,mid+1,qr,mid+1,r));
            }
            int getmin(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r)return tr[now].mn;
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                     if(r<=mid)  return getmin(lc,ql,mid,l,r);
                else if(mid+1<=l)return getmin(rc,mid+1,qr,l,r);
                else return min(getmin(lc,ql,mid,l,mid),getmin(rc,mid+1,qr,mid+1,r));
            }
        }
        //~~~~~~~~~~~~~~getnum~~~~~~~~~~~~~~~~~
        
        int z,pos[maxn];
        int dep[maxn],fa[mbit][maxn];
        void dfs(int x,int fr)
        {
            pos[++z]=x;
            Segtree::change(1,1,n,d[x],z);
            for(int i=1;(1<<i)<=dep[x];i++)fa[i][x]=fa[i-1][fa[i-1][x]];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(y!=fa[0][x])
                {
                    fa[0][y]=x;
                    dep[y]=dep[x]+1;
                    dfs(y,x);
                }
            }
        }
        int LCA(int x,int y)
        {
            if(dep[x]<dep[y])swap(x,y);
            for(int i=25;i>=0;i--)
                if(dep[x]-dep[y]>=(1<<i))x=fa[i][x];
            if(x==y)return x;
            for(int i=25;i>=0;i--)
                if(dep[x]>=(1<<i)&&fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y];
            return fa[0][x];
        }
        int getnum(int l,int r)
        {
            return dep[LCA(pos[Segtree::getmax(1,1,n,l,r)],pos[Segtree::getmin(1,1,n,l,r)])];
        }
        //~~~~~~~~~~~~~~~make~~~~~~~~~~~~~~~~~
        
        int ls[maxn],id[maxn];
        bool cmp(int x,int y){return d[x]<d[y];}
        int getl(int l){return lower_bound(ls+1,ls+n+1,l)-ls;}
        int getr(int r){return upper_bound(ls+1,ls+n+1,r)-ls-1;}
        void LSH()
        {
            for(int i=1;i<=n;i++)ls[i]=d[i],id[i]=i;
            sort(ls+1,ls+n+1);
            sort(id+1,id+n+1,cmp);
            for(int i=1;i<=n;i++)d[id[i]]=i;
        }
        //~~~~~~~~~~~~~~~~LSH~~~~~~~~~~~~~~~~
        
        void main(){LSH();dfs(1,0);}
    }
    
    //--------------------------------------------------------------------------------------------
    
    namespace COUNT
    {
        namespace Chair
        {
            struct chairmantree
            {
                int lc,rc,c;
            }tr[100*maxn];int trlen,rt[maxn];
            int insert(int x,int ql,int qr,int p,int c)
            {
                if(x==0)x=++trlen;
                tr[x].c+=c;
                if(ql==qr)return x;
                int mid=(ql+qr)/2;
                if(p<=mid)tr[x].lc=insert(tr[x].lc,ql,mid,p,c);
                else tr[x].rc=insert(tr[x].rc,mid+1,qr,p,c);
                return x;
            }
            int merge(int x,int y)
            {
                if(x==0||y==0)return x+y;
                tr[x].c+=tr[y].c;
                tr[x].lc=merge(tr[x].lc,tr[y].lc);
                tr[x].rc=merge(tr[x].rc,tr[y].rc);
                return x;
            }
            int getsum(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r){return tr[now].c;}
                int lc=tr[now].lc,rc=tr[now].rc,mid=(ql+qr)/2;
                      if(r<=mid)  return getsum(lc,ql,mid,l,r);
                else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r);
                else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r);
            }
            
            void newid(int &x,int &y){x++,y=n+1-y+1;}
            void paint(int x,int y,int c)
            {
                newid(x,y);
                rt[x]=insert(rt[x],1,n+1,y,c);
            }
            int getnum(int x,int y)
            {
                newid(x,y);
                return getsum(rt[x],1,n+1,1,y);
            }
            void pre()
            {
                for(int i=1;i<=n+1;i++)
                    rt[i]=merge(rt[i],rt[i-1]);
            }
        }
        namespace Splay
        {
            struct splay
            {
                int f,son[2];
                int q,x,c,lazy;
            }tr[30*maxn];int trlen,rt[maxn],tot[maxn],id[2*30*maxn],idtp;
            void init(){for(int i=1;i<30*maxn;i++)id[i]=i;idtp=30*maxn;}
            void tap(int w){tr[rt[w]].c++,tr[rt[w]].lazy++;}
            void rotate(int x,int w)
            {
                int f=tr[x].f,ff=tr[f].f;
                int R,r;
                
                R=f,r=tr[x].son[w];
                tr[R].son[1-w]=r;
                if(r!=0)tr[r].f=R;
                
                R=ff,r=x;
                if(tr[ff].son[0]==f)tr[R].son[0]=r;
                else tr[R].son[1]=r;
                tr[r].f=R;
                
                R=x,r=f;
                tr[R].son[w]=r;
                tr[r].f=R;
            }
            void pushdown(int now)
            {
                int lc=tr[now].son[0],rc=tr[now].son[1];
                tr[lc].c+=tr[now].lazy,tr[lc].lazy+=tr[now].lazy;
                tr[rc].c+=tr[now].lazy,tr[rc].lazy+=tr[now].lazy;
                tr[now].lazy=0;
            }
            int tt,tmp[maxn];
            void splay(int x,int F,int w)
            {
                int i=x; tt=0;
                while(i!=F)
                    tmp[++tt]=i,i=tr[i].f;
                while(tt>0)
                { 
                    if(tr[tmp[tt]].lazy!=0)pushdown(tmp[tt]);
                    tt--;
                }
                 
                while(tr[x].f!=F)
                {
                    int f=tr[x].f,ff=tr[f].f;
                    if(ff==F)
                    {
                        if(tr[f].son[0]==x)rotate(x,1);
                        else rotate(x,0);
                    }
                    else
                    {
                             if(tr[ff].son[0]==f&&tr[f].son[0]==x)rotate(f,1),rotate(x,1);
                        else if(tr[ff].son[1]==f&&tr[f].son[1]==x)rotate(f,0),rotate(x,0);
                        else if(tr[ff].son[0]==f&&tr[f].son[1]==x)rotate(x,0),rotate(x,1);
                        else if(tr[ff].son[1]==f&&tr[f].son[0]==x)rotate(x,1),rotate(x,0);
                    }
                }
                if(F==0)rt[w]=x;
            }
            //~~~~~~~~~~~~~~~~~~~~in~~~~~~~~~~~~~~~~~~~~~~
            
            int findip(int w,int d)
            {
                int x=rt[w];
                while(1)
                {
                    pushdown(x);
                    int lc=tr[x].son[0],rc=tr[x].son[1];
                    if(d<tr[x].x)
                    {
                        if(lc==0)return x;
                        x=lc;
                    }
                    else
                    {
                        if(rc==0)return x;
                        x=rc;
                    }
                }
            }
            int findqq(int x,int w)
            {
                splay(x,0,w);
                x=tr[x].son[0];
                while(tr[x].son[1]!=0)x=tr[x].son[1];
                return x;
            }
            int findhj(int x,int w)
            {
                splay(x,0,w);
                x=tr[x].son[1];
                while(tr[x].son[0]!=0)x=tr[x].son[0];
                return x;
            }
            //~~~~~~~~~~~~~~~~~~~find~~~~~~~~~~~~~~~~~~~~~~
            
            void add(int x)
            {
                trlen++; if(trlen==2*30*maxn)trlen=1;
                tr[id[trlen]].x=x;
                tr[id[trlen]].c=0,tr[id[trlen]].lazy=0; 
            }
            void insert(int w,int d)
            {
                tot[w]++;add(d);
                if(rt[w]==0)rt[w]=id[trlen];
                else if(tot[w]==2)
                {
                    tr[rt[w]].son[1]=id[trlen];
                    tr[id[trlen]].f=rt[w];
                    tr[id[trlen]].q=0;
                }
                else
                {
                    int p=findip(w,d);
                     if(d<tr[p].x)tr[p].son[0]=id[trlen];
                    else tr[p].son[1]=id[trlen];
                    tr[id[trlen]].f=p;
                    
                    tr[id[trlen]].q=tr[findqq(id[trlen],w)].x;
                    int h=findhj(id[trlen],w);splay(h,0,w);
                    if(tr[h].c!=0)Chair::paint(tr[h].q,tr[h].x,tr[h].c),tr[h].c=0;
                    tr[h].q=tr[id[trlen]].x;
                }
            }
            //~~~~~~~~~~~~~~~~~base~~~~~~~~~~~~~~~~~~~~~~~~
            
            void dfs(int w,int x)
            {
                if(tr[x].c!=0&&tr[x].x!=0)Chair::paint(tr[x].q,tr[x].x,tr[x].c);
                if(tr[x].x!=0&&tr[x].x!=n+1)
                {
                    insert(w,tr[x].x);
                    id[idtp++]=x;
                    if(idtp==2*30*maxn)idtp=1;
                }
                pushdown(x);
                if(tr[x].son[0]!=0)dfs(w,tr[x].son[0]);
                if(tr[x].son[1]!=0)dfs(w,tr[x].son[1]);
            }
            void merge(int x,int y) 
            {
                if(tot[x]<tot[y])swap(rt[x],rt[y]),swap(tot[x],tot[y]);
                dfs(x,rt[y]);
            }
            void dfs2(int x)
            {
                if(tr[x].c!=0&&tr[x].x!=0)Chair::paint(tr[x].q,tr[x].x,tr[x].c);
                pushdown(x);
                if(tr[x].son[0]!=0)dfs2(tr[x].son[0]);
                if(tr[x].son[1]!=0)dfs2(tr[x].son[1]);
            }
            void divi(){dfs2(rt[1]);}
        }
        
        void dfs(int x,int fr)
        {
            for(int k=last[x];k;k=a[k].next)
                if(a[k].y!=fr)dfs(a[k].y,x);
            Splay::insert(x,0);
            Splay::insert(x,n+1);
            Splay::insert(x,d[x]);
            for(int k=last[x];k;k=a[k].next)
                if(a[k].y!=fr)Splay::merge(x,a[k].y);
            Splay::tap(x);
        }
        void main()
        {
            Splay::init();dfs(1,0);
            Splay::divi();
            Chair::pre();
        }
    }
    
    //--------------------------------------------------------------------------------------------
    
    namespace QUERY
    {
        void main()
        {
            int l,r;
            while(Q--)
            {
                l=read(),r=read();
                l=TREE::getl(l);
                r=TREE::getr(r);
                if(l>r)puts("0");
                else write(n- (TREE::getnum(l,r)) - (COUNT::Chair::getnum(l-1,r+1)) ),putchar('
    ');
            }
        }
    }
    
    //--------------------------------------------------------------------------------------------
    
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int x,y;
        n=read(),Q=read();
        for(int i=1;i<=n;i++)d[i]=read();
        for(int i=1;i<n;i++)
        {
            x=read(),y=read();
            ins(x,y),ins(y,x);
        }
        TREE::main();
        COUNT::main();
        QUERY::main();
        
        return 0;
    }
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int _=1e2;
    const int maxn=1e5+_;
    const int maxQ=5e5+_;
    const int mbit=30;
    const int fbin=(1<<17)+_;
    int read()
    {
        int x=0,f=1; char ch=getchar();
        while(!isdigit(ch))ch=getchar();
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    void write(int x)
    {
        if(x>=10)write(x/10);
        putchar(x%10+'0');
    }
    int n,Q;
    struct node
    {
        int x,y,next;
    }a[2*maxn];int len,last[maxn],d[maxn];
    void ins(int x,int y)
    {
        len++;
        a[len].x=x;a[len].y=y;
        a[len].next=last[x];last[x]=len;
    }
    
    //--------------------------------------------def-------------------------------------------------------
    
    namespace TREE
    {
        namespace Segtree
        {
            struct segtree{int mx,mn;segtree(){mn=(1<<30);}}tr[2*fbin];
            void update(int now)
            {
                int lc=(now<<1),rc=(now<<1|1);
                tr[now].mx=max(tr[lc].mx,tr[rc].mx);
                tr[now].mn=min(tr[lc].mn,tr[rc].mn);
            }
            void pushdown(int now)
            {
                int lc=(now<<1),rc=(now<<1|1);
                tr[lc].mx=max(tr[now].mx,tr[lc].mx);
                tr[rc].mn=min(tr[now].mn,tr[rc].mn);
            }
            void change(int now,int ql,int qr,int p,int k)
            {
                if(ql==qr)
                {
                    tr[now].mx=max(tr[now].mx,k);
                    tr[now].mn=min(tr[now].mn,k);
                    return ;
                }
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                if(p<=mid)change(lc,ql,mid,p,k);
                else change(rc,mid+1,qr,p,k);
                update(now);
            }
            int getmax(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r)return tr[now].mx;
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                     if(r<=mid)  return getmax(lc,ql,mid,l,r);
                else if(mid+1<=l)return getmax(rc,mid+1,qr,l,r);
                else return max(getmax(lc,ql,mid,l,mid),getmax(rc,mid+1,qr,mid+1,r));
            }
            int getmin(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r)return tr[now].mn;
                int lc=(now<<1),rc=(now<<1|1),mid=(ql+qr)/2;
                pushdown(now);
                     if(r<=mid)  return getmin(lc,ql,mid,l,r);
                else if(mid+1<=l)return getmin(rc,mid+1,qr,l,r);
                else return min(getmin(lc,ql,mid,l,mid),getmin(rc,mid+1,qr,mid+1,r));
            }
        }
        //~~~~~~~~~~~~~~getnum~~~~~~~~~~~~~~~~~
        
        int z,pos[maxn];
        int dep[maxn],fa[mbit][maxn];
        void dfs(int x,int fr)
        {
            pos[++z]=x;
            Segtree::change(1,1,n,d[x],z);
            for(int i=1;(1<<i)<=dep[x];i++)fa[i][x]=fa[i-1][fa[i-1][x]];
            for(int k=last[x];k;k=a[k].next)
            {
                int y=a[k].y;
                if(y!=fa[0][x])
                {
                    fa[0][y]=x;
                    dep[y]=dep[x]+1;
                    dfs(y,x);
                }
            }
        }
        int LCA(int x,int y)
        {
            if(dep[x]<dep[y])swap(x,y);
            for(int i=25;i>=0;i--)
                if(dep[x]-dep[y]>=(1<<i))x=fa[i][x];
            if(x==y)return x;
            for(int i=25;i>=0;i--)
                if(dep[x]>=(1<<i)&&fa[i][x]!=fa[i][y])x=fa[i][x],y=fa[i][y];
            return fa[0][x];
        }
        int getnum(int l,int r)
        {
            return dep[LCA(pos[Segtree::getmax(1,1,n,l,r)],pos[Segtree::getmin(1,1,n,l,r)])];
        }
        //~~~~~~~~~~~~~~~make~~~~~~~~~~~~~~~~~
        
        int ls[maxn],id[maxn];
        bool cmp(int x,int y){return d[x]<d[y];}
        int getl(int l){return lower_bound(ls+1,ls+n+1,l)-ls;}
        int getr(int r){return upper_bound(ls+1,ls+n+1,r)-ls-1;}
        void LSH()
        {
            for(int i=1;i<=n;i++)ls[i]=d[i],id[i]=i;
            sort(ls+1,ls+n+1);
            sort(id+1,id+n+1,cmp);
            for(int i=1;i<=n;i++)d[id[i]]=i;
        }
        //~~~~~~~~~~~~~~~~LSH~~~~~~~~~~~~~~~~
        
        void main(){LSH();dfs(1,0);}
    }
    
    //--------------------------------------------------------------------------------------------
    
    namespace COUNT
    {
        namespace Chair
        {
            struct chairmantree
            {
                int lc,rc,c;
            }tr[100*maxn];int trlen,rt[maxn];
            int insert(int x,int ql,int qr,int p,int c)
            {
                if(x==0)x=++trlen;
                tr[x].c+=c;
                if(ql==qr)return x;
                int mid=(ql+qr)/2;
                if(p<=mid)tr[x].lc=insert(tr[x].lc,ql,mid,p,c);
                else tr[x].rc=insert(tr[x].rc,mid+1,qr,p,c);
                return x;
            }
            int merge(int x,int y)
            {
                if(x==0||y==0)return x+y;
                tr[x].c+=tr[y].c;
                tr[x].lc=merge(tr[x].lc,tr[y].lc);
                tr[x].rc=merge(tr[x].rc,tr[y].rc);
                return x;
            }
            int getsum(int now,int ql,int qr,int l,int r)
            {
                if(ql==l&&qr==r){return tr[now].c;}
                int lc=tr[now].lc,rc=tr[now].rc,mid=(ql+qr)/2;
                      if(r<=mid)  return getsum(lc,ql,mid,l,r);
                else if(mid+1<=l)return getsum(rc,mid+1,qr,l,r);
                else return getsum(lc,ql,mid,l,mid)+getsum(rc,mid+1,qr,mid+1,r);
            }
            
            void newid(int &x,int &y){x++,y=n+1-y+1;}
            void paint(int x,int y,int c)
            {
                newid(x,y);
                rt[x]=insert(rt[x],1,n+1,y,c);
            }
            int getnum(int x,int y)
            {
                newid(x,y);
                return getsum(rt[x],1,n+1,1,y);
            }
            void pre()
            {
                for(int i=1;i<=n+1;i++)
                    rt[i]=merge(rt[i],rt[i-1]);
            }
        }
        namespace Splay
        {
            struct splay
            {
                int f,son[2];
                int q,x,c,lazy;
            }tr[30*maxn];int trlen,rt[maxn],tot[maxn],id[2*30*maxn],idtp;
            void init(){for(int i=1;i<30*maxn;i++)id[i]=i;idtp=30*maxn;}
            void tap(int w){tr[rt[w]].c++,tr[rt[w]].lazy++;}
            void rotate(int x,int w)
            {
                int f=tr[x].f,ff=tr[f].f;
                int R,r;
                
                R=f,r=tr[x].son[w];
                tr[R].son[1-w]=r;
                if(r!=0)tr[r].f=R;
                
                R=ff,r=x;
                if(tr[ff].son[0]==f)tr[R].son[0]=r;
                else tr[R].son[1]=r;
                tr[r].f=R;
                
                R=x,r=f;
                tr[R].son[w]=r;
                tr[r].f=R;
            }
            void pushdown(int now)
            {
                int lc=tr[now].son[0],rc=tr[now].son[1];
                tr[lc].c+=tr[now].lazy,tr[lc].lazy+=tr[now].lazy;
                tr[rc].c+=tr[now].lazy,tr[rc].lazy+=tr[now].lazy;
                tr[now].lazy=0;
            }
            int tt,tmp[maxn];
            void splay(int x,int F,int w)
            {
                int i=x; tt=0;
                while(i!=F)
                    tmp[++tt]=i,i=tr[i].f;
                while(tt>0)
                { 
                    if(tr[tmp[tt]].lazy!=0)pushdown(tmp[tt]);
                    tt--;
                }
                 
                while(tr[x].f!=F)
                {
                    int f=tr[x].f,ff=tr[f].f;
                    if(ff==F)
                    {
                        if(tr[f].son[0]==x)rotate(x,1);
                        else rotate(x,0);
                    }
                    else
                    {
                             if(tr[ff].son[0]==f&&tr[f].son[0]==x)rotate(f,1),rotate(x,1);
                        else if(tr[ff].son[1]==f&&tr[f].son[1]==x)rotate(f,0),rotate(x,0);
                        else if(tr[ff].son[0]==f&&tr[f].son[1]==x)rotate(x,0),rotate(x,1);
                        else if(tr[ff].son[1]==f&&tr[f].son[0]==x)rotate(x,1),rotate(x,0);
                    }
                }
                if(F==0)rt[w]=x;
            }
            //~~~~~~~~~~~~~~~~~~~~in~~~~~~~~~~~~~~~~~~~~~~
            
            int findip(int w,int d)
            {
                int x=rt[w];
                while(1)
                {
                    pushdown(x);
                    int lc=tr[x].son[0],rc=tr[x].son[1];
                    if(d<tr[x].x)
                    {
                        if(lc==0)return x;
                        x=lc;
                    }
                    else
                    {
                        if(rc==0)return x;
                        x=rc;
                    }
                }
            }
            int findqq(int x,int w)
            {
                splay(x,0,w);
                x=tr[x].son[0];
                while(tr[x].son[1]!=0)x=tr[x].son[1];
                return x;
            }
            int findhj(int x,int w)
            {
                splay(x,0,w);
                x=tr[x].son[1];
                while(tr[x].son[0]!=0)x=tr[x].son[0];
                return x;
            }
            //~~~~~~~~~~~~~~~~~~~find~~~~~~~~~~~~~~~~~~~~~~
            
            void add(int x)
            {
                trlen++; if(trlen==2*30*maxn)trlen=1;
                tr[id[trlen]].x=x;
                tr[id[trlen]].c=0,tr[id[trlen]].lazy=0; 
            }
            void insert(int w,int d)
            {
                tot[w]++;add(d);
                if(rt[w]==0)rt[w]=id[trlen];
                else if(tot[w]==2)
                {
                    tr[rt[w]].son[1]=id[trlen];
                    tr[id[trlen]].f=rt[w];
                    tr[id[trlen]].q=0;
                }
                else
                {
                    int p=findip(w,d);
                     if(d<tr[p].x)tr[p].son[0]=id[trlen];
                    else tr[p].son[1]=id[trlen];
                    tr[id[trlen]].f=p;
                    
                    tr[id[trlen]].q=tr[findqq(id[trlen],w)].x;
                    int h=findhj(id[trlen],w);splay(h,0,w);
                    if(tr[h].c!=0)Chair::paint(tr[h].q,tr[h].x,tr[h].c),tr[h].c=0;
                    tr[h].q=tr[id[trlen]].x;
                }
            }
            //~~~~~~~~~~~~~~~~~base~~~~~~~~~~~~~~~~~~~~~~~~
            
            void dfs(int w,int x)
            {
                if(tr[x].c!=0&&tr[x].x!=0)Chair::paint(tr[x].q,tr[x].x,tr[x].c);
                if(tr[x].x!=0&&tr[x].x!=n+1)
                {
                    insert(w,tr[x].x);
                    id[idtp++]=x;
                    if(idtp==2*30*maxn)idtp=1;
                }
                pushdown(x);
                if(tr[x].son[0]!=0)dfs(w,tr[x].son[0]);
                if(tr[x].son[1]!=0)dfs(w,tr[x].son[1]);
            }
            void merge(int x,int y) 
            {
                if(tot[x]<tot[y])swap(rt[x],rt[y]),swap(tot[x],tot[y]);
                dfs(x,rt[y]);
            }
            void dfs2(int x)
            {
                if(tr[x].c!=0&&tr[x].x!=0)Chair::paint(tr[x].q,tr[x].x,tr[x].c);
                pushdown(x);
                if(tr[x].son[0]!=0)dfs2(tr[x].son[0]);
                if(tr[x].son[1]!=0)dfs2(tr[x].son[1]);
            }
            void divi(){dfs2(rt[1]);}
        }
        
        void dfs(int x,int fr)
        {
            for(int k=last[x];k;k=a[k].next)
                if(a[k].y!=fr)dfs(a[k].y,x);
            Splay::insert(x,0);
            Splay::insert(x,n+1);
            Splay::insert(x,d[x]);
            for(int k=last[x];k;k=a[k].next)
                if(a[k].y!=fr)Splay::merge(x,a[k].y);
            Splay::tap(x);
        }
        void main()
        {
            Splay::init();dfs(1,0);
            Splay::divi();
            Chair::pre();
        }
    }
    
    //--------------------------------------------------------------------------------------------
    
    namespace QUERY
    {
        void main()
        {
            int l,r;
            while(Q--)
            {
                l=read(),r=read();
                l=TREE::getl(l);
                r=TREE::getr(r);
                if(l>r)puts("0");
                else write(n- (TREE::getnum(l,r)) - (COUNT::Chair::getnum(l-1,r+1)) ),putchar('
    ');
            }
        }
    }
    
    //--------------------------------------------------------------------------------------------
    
    
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int x,y;
        n=read(),Q=read();
        for(int i=1;i<=n;i++)d[i]=read();
        for(int i=1;i<n;i++)
        {
            x=read(),y=read();
            ins(x,y),ins(y,x);
        }
        TREE::main();
        COUNT::main();
        QUERY::main();
        
        return 0;
    }
  • 相关阅读:
    C语言作业(心理魔术)
    心理魔术
    作业
    作业
    自定义打包小游戏的build template,接入SDK,
    JavaScript_call,bind,apply的区别
    JavaScript原型链的理解
    学习笔记—前端基础之ES6的数组
    学习笔记 — 前端基础之ES6(2)
    学习笔记 — 前端基础之ES6(1)
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10599411.html
Copyright © 2020-2023  润新知