LOJ #2107. 「JLOI2015」城池攻占 Splay+启发式合并

这道题拿左偏树做的话时间复杂度好像是 $O(n \log n)$ 的,拿 $Splay$ 的话就是 $O(n \log^2 n)$ 的.   

$Splay$ 真恶心,真心不好写,要不是可以练习代码能力的话我才不用 $Splay$.  

code:   

#include <bits/stdc++.h>       
#define ll long long       
#define N 300006 
#define setIO(s) freopen(s".in","r",stdin) ,freopen(s".out","w",stdout)  
using namespace std;  
const ll inf=7e18+2;   
ll h[N];
struct opt 
{
    int a;  
    ll v;     
}tree[N];       
int DE;       
int n,m,edges,tot,FL,Ans1[N],Ans2[N],ge[N];         
int dep[N],hd[N],to[N],nex[N],rt[N],ou[N];            
namespace BST
{  
    #define lson s[x].ch[0] 
    #define rson s[x].ch[1]  
    struct node 
    {   
        ll v,a,b;  
        int si,ch[2],f,id;  
        void ini() 
        {
            v=0,a=1,b=0;    
            si=1,ch[0]=ch[1]=f=id=0;  
        }   
    }s[N*20];    
    int tot;  
    stack<int>S;       
    inline int get(int x) { return s[s[x].f].ch[1]==x; }   
    inline int newnode()  
    {
        if(S.empty()) 
            return ++tot;   
        else
        {
            int u=S.top(); 
            S.pop();  
            return u;   
        }
    }    
    inline void pushup(int x) 
    {
        s[x].si=s[lson].si+s[rson].si+1;  
    }
    inline void mark_a(int x,ll a) 
    {
        s[x].a*=a,s[x].b*=a;     
        if(s[x].v!=inf&&s[x].v!=-inf)   
            s[x].v*=a;        
    }
    inline void mark_b(int x,ll b) 
    {
        s[x].b+=b;   
        if(s[x].v!=inf&&s[x].v!=-inf)   
            s[x].v+=b;   
    }
    inline void pushdown(int x) 
    {
        if(s[x].a!=1) 
        {
            if(lson)  
                mark_a(lson,s[x].a);  
            if(rson) 
                mark_a(rson,s[x].a);  
            s[x].a=1; 
        }
        if(s[x].b) 
        {
            if(lson) 
                mark_b(lson,s[x].b);  
            if(rson) 
                mark_b(rson,s[x].b);   
            s[x].b=0;  
        }
    }
    int ins(int &x,int ff,int id,ll v) 
    {
        if(!x) 
        {
            x=newnode();       
            s[x].ini();  
            s[x].f=ff,s[x].id=id,s[x].v=v; 
            return x;      
        }      
        ++s[x].si;  
        pushdown(x);     
        return ins(s[x].ch[v>s[x].v],x,id,v); 
    }  
    inline int find(int x,ll v) 
    {
        int r=0;    
        while(1) 
        {    
            if(!x) 
                break;  
            pushdown(x);       
            if(s[x].v>=v)  
                r=x,x=lson;    
            else 
                x=rson;  
        }
        return r;   
    }   
    inline void rotate(int x) 
    {
        int old=s[x].f,fold=s[old].f,which=get(x);  
        s[old].ch[which]=s[x].ch[which^1];  
        if(s[old].ch[which]) 
            s[s[old].ch[which]].f=old;  
        s[x].ch[which^1]=old,s[old].f=x,s[x].f=fold;  
        if(fold)  
            s[fold].ch[s[fold].ch[1]==old]=x;   
        pushup(old),pushup(x); 
    }
    void splay(int x,int &tar) 
    {
        int u=s[tar].f;  
        for(int fa;(fa=s[x].f)!=u;rotate(x))     
            if(s[fa].f!=u)  
                rotate(get(fa)==get(x)?fa:x);  
        tar=x;  
    }    
    void ope(int &x,int y) 
    {      
        if(s[y].v!=-inf&&s[y].v!=inf)   
        { 
            int p=ins(x,0,s[y].id,s[y].v);    
            if((rand()%3)==0)   
                splay(p,x);                          
        }
        pushdown(y);   
        if(s[y].ch[0])  
            ope(x,s[y].ch[0]);   
        if(s[y].ch[1]) 
            ope(x,s[y].ch[1]);   
        S.push(y);     
    }        
    void del(int x) 
    {    
        if(!x)  
            return;   
        if(s[x].v!=inf&&s[x].v!=-inf) 
        {   
            Ans1[FL]+=1;     
            ou[s[x].id]=1;   
            Ans2[s[x].id]+=dep[ge[s[x].id]]-dep[FL];       
        }    
        pushdown(x);   
        if(lson)   
            del(lson);  
        if(rson)  
            del(rson);   
        S.push(x);   
    }  
    #undef lson 
    #undef rson  
};                
void add(int u,int v) 
{
    nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;   
}      
void merge(int x,int y) 
{  
    if(BST::s[rt[x]].si<BST::s[rt[y]].si)       
        swap(rt[x],rt[y]);  
    BST::ope(rt[x],rt[y]);   
}               
void dfs(int x,int ff) 
{
    dep[x]=dep[ff]+1;           
    BST::ins(rt[x],0,0,inf);  
    BST::ins(rt[x],0,0,-inf);     
    for(int i=hd[x];i;i=nex[i]) 
    {
        int y=to[i];      
        dfs(y,x),merge(x,y);  
    }       
    FL=x;    
    int q=BST::find(rt[x],h[x]);                                 
    BST::splay(q,rt[x]);             
    BST::s[BST::s[q].ch[0]].f=0; 
    BST::del(BST::s[q].ch[0]);   
    BST::s[q].ch[0]=0;                           
    BST::pushup(q);                                             
    if(x!=1)                
    {
        if(tree[x].a==0)   
            BST::mark_b(q,tree[x].v);   
        if(tree[x].a==1)  
            BST::mark_a(q,tree[x].v);         
    }                     
}
int main() 
{ 
    // setIO("input");     
    int i,j;    
    scanf("%d%d",&n,&m);         
    for(i=1;i<=n;++i)          
        scanf("%lld",&h[i]);         
    for(i=2;i<=n;++i)      
        scanf("%d%d%lld",&j,&tree[i].a,&tree[i].v),add(j,i);            
    for(i=1;i<=m;++i) 
    {
        ll v; 
        int u;        
        scanf("%lld%d",&v,&u);     
        ge[i]=u;  
        BST::ins(rt[u],0,i,v);        
    }     
    dfs(1,0);       
    for(i=1;i<=n;++i)   
        printf("%d\n",Ans1[i]);  
    for(i=1;i<=m;++i)  
        if(!ou[i])      
            printf("%d\n",dep[ge[i]]);  
        else 
            printf("%d\n",Ans2[i]);  
    return 0;
}

  

posted @ 2020-03-12 21:59  EM-LGH  阅读(161)  评论(0编辑  收藏  举报