LOJ #2831. 「JOISC 2018 Day 1」道路建设 线段树+Link-cut-tree

用 LCT 维护颜色相同连通块,然后在线段树上查一下逆序对个数就可以了. 

code:

#include <cstdio> 
#include <algorithm> 
#include <cstring>     
#include <string>     
#define N 100005 
#define ll long long 
using namespace std;      
namespace IO 
{ 
    void setIO(string s) 
    {
        string in=s+".in"; 
        string out=s+".out"; 
        freopen(in.c_str(),"r",stdin); 
        // freopen(out.c_str(),"w",stdout);  
    }
};  
ll ans;   
int n,val[N],A[N];     
namespace seg 
{     
    int lazy[N<<2],sum[N<<2];      
    void mark(int now) { sum[now]=0,lazy[now]=1; }    
    void pushdown(int now) 
    { 
        if(lazy[now])  
            mark(now<<1),mark(now<<1|1),lazy[now]=0; 
    }       
    void update(int l,int r,int now,int p,int v) 
    {
        if(l==r) { sum[now]+=v;   return; }    
        pushdown(now);  
        int mid=(l+r)>>1;     
        if(p<=mid)  
            update(l,mid,now<<1,p,v);  
        else 
            update(mid+1,r,now<<1|1,p,v);  
        sum[now]=sum[now<<1]+sum[now<<1|1];   
    }
    int query(int l,int r,int now,int L,int R) 
    { 
        if(L>R) 
            return 0;  
        if(l>=L&&r<=R)  
            return sum[now];  
        pushdown(now);         
        int re=0,mid=(l+r)>>1;  
        if(L<=mid)   
            re+=query(l,mid,now<<1,L,R);   
        if(R>mid)  
            re+=query(mid+1,r,now<<1|1,L,R);  
        return re;  
    }
};  
namespace LCT 
{ 
    #define lson s[x].ch[0] 
    #define rson s[x].ch[1]  
    struct node { 
        int ch[2],rev,f,tag,size;     
    }s[N];       
    int sta[N];  
    inline int get(int x) { return s[s[x].f].ch[1]==x; }   
    inline int isr(int x) { return s[s[x].f].ch[0]!=x&&s[s[x].f].ch[1]!=x; }      
    inline void pushup(int x)     { s[x].size=s[lson].size+s[rson].size+1; }    
    inline void mark(int x,int v) { s[x].tag=v; }    
    inline void pushdown(int x) 
    {
        if(lson) mark(lson,s[x].tag);  
        if(rson) mark(rson,s[x].tag);            
    }
    inline void rotate(int x) 
    {     
        int old=s[x].f,fold=s[old].f,which=get(x);  
        if(!isr(old))      
            s[fold].ch[s[fold].ch[1]==old]=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;    
        pushup(old),pushup(x);          
    } 
    inline void splay(int x) 
    {     
        int v=0,u=x,fa;  
        for(sta[++v]=u;!isr(u);u=s[u].f) 
            sta[++v]=s[u].f;              
        for(;v;--v) 
            pushdown(sta[v]);   
        for(u=s[u].f;(fa=s[x].f)!=u;rotate(x)) 
            if(s[fa].f!=u) 
                rotate(get(fa)==get(x)?fa:x);  
    }     
    inline void Access(int x,int v) 
    {  
        for(int y=0;x;y=x,x=s[x].f)  
        { 
            splay(x),rson=0,pushup(x);   
            ans+=(ll)s[x].size*seg::query(1,n,1,1,s[x].tag-1);     
            seg::update(1,n,1,s[x].tag,s[x].size);    
            rson=y,s[x].tag=v,pushup(x);    
        }
    }   
    inline void link(int x,int y) { s[y].f=x; }    
    #undef lson 
    #undef rson                    
};  
int main() 
{ 
    // IO::setIO("input");  
    int i,j;           
    scanf("%d",&n);  
    for(i=1;i<=n;++i)  
        scanf("%d",&val[i]),A[i]=val[i]; 
    sort(A+1,A+1+n);  
    for(i=1;i<=n;++i) 
        val[i]=lower_bound(A+1,A+1+n,val[i])-A,LCT::s[i].tag=val[i];    
    for(i=1;i<n;++i) 
    {
        int x,y;    
        scanf("%d%d",&x,&y);      
        ans=0;  
        seg::mark(1);            
        LCT::Access(x,val[y]);     
        LCT::link(x,y);   
        printf("%lld
",ans);       
    }
    return 0;
}               

  

原文地址:https://www.cnblogs.com/guangheli/p/12377889.html