牛客练习赛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;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/10599411.html