• 【洛谷P4319】 变化的道路 线段树分治+LCT


    最近学了一下线段树分治,感觉还蛮好用...

    如果正常动态维护最大生成树的话用 LCT 就行,但是这里还有时间这一维的限制. 

    所以,我们就把每条边放到以时间为轴的线段树的节点上,然后写一个可撤销 LCT 就好了 ~ 

    code: 

    #include <bits/stdc++.h> 
    #define RM 32766 
    #define N 2000005   
    #define ll long long 
    #define setIO(s)    freopen(s".in","r",stdin) , freopen(s".out","w",stdout)   
    using namespace std;            
    namespace LCT 
    {   
        #define lson t[x].ch[0] 
        #define rson t[x].ch[1] 
        struct node 
        {   
            ll sum;   
            int f,ch[2],rev,w,maxx,id;               
        }t[N];       
        int sta[N]; 
        inline int get(int x) { return t[t[x].f].ch[1]==x; }   
        inline int Irt(int x) { return !(t[t[x].f].ch[0]==x||t[t[x].f].ch[1]==x); }        
        inline void mark(int x) 
        {
            if(!x)    return;    
            swap(lson,rson), t[x].rev^=1;   
        } 
        inline void pushdown(int x) 
        {
            if(x&&t[x].rev) 
            {
                if(lson)     mark(lson); 
                if(rson)     mark(rson); 
                t[x].rev=0;   
            }
        }     
        inline void pushup(int x) 
        {   
            t[x].id=x;  
            t[x].sum=t[x].w;  
            t[x].maxx=t[x].w;   
            if(lson)    
            {
                t[x].sum+=t[lson].sum;   
                if(t[lson].maxx>t[x].maxx) 
                {
                    t[x].id=t[lson].id;  
                    t[x].maxx=t[lson].maxx;  
                } 
            }
            if(rson)    
            {
                t[x].sum+=t[rson].sum; 
                if(t[rson].maxx>t[x].maxx) 
                {
                    t[x].id=t[rson].id; 
                    t[x].maxx=t[rson].maxx;  
                }       
            }
        }
        inline void rotate(int x) 
        {
            int old=t[x].f,fold=t[old].f,which=get(x);    
            if(!Irt(old))   t[fold].ch[t[fold].ch[1]==old]=x; 
            t[old].ch[which]=t[x].ch[which^1], t[t[old].ch[which]].f=old;       
            t[x].ch[which^1]=old,t[old].f=x,t[x].f=fold;   
            pushup(old), pushup(x);   
        }
        inline void splay(int x) 
        {
            int u=x,v=0,fa;  
            for(sta[++v]=u;!Irt(u);u=t[u].f)       sta[++v]=t[u].f;   
            for(;v;--v)     pushdown(sta[v]);   
            for(u=t[u].f;(fa=t[x].f)!=u;rotate(x))  if(t[fa].f!=u)   rotate(get(fa)==get(x)?fa:x); 
        }
        inline void Access(int x) 
        { 
            for(int y=0;x;y=x,x=t[x].f)   splay(x),rson=y,pushup(x);  
        }
        inline void MakeRT(int x) 
        { 
            Access(x),splay(x),mark(x);  
        }
        inline void Link(int x,int y) 
        {
            MakeRT(y),t[y].f=x; 
        } 
        inline void split(int x,int y) 
        { 
            MakeRT(x),Access(y),splay(y); 
        }
        inline void cut(int x,int y) 
        {
            MakeRT(y),Access(x),splay(x);   
            t[x].ch[0]=t[y].f=0;  
            pushup(x);   
        }
        inline int findroot(int x) 
        {       
            for(Access(x),splay(x);lson;x=lson);  
            return x; 
        }
        #undef lson 
        #undef rson 
    };   
    #define lson now<<1 
    #define rson now<<1|1  
    int n; 
    int tag[N];  
    vector<int>G[N<<2];  
    struct edge
    {   
        int u,v,w;  
        edge(int u=0,int v=0,int w=0):u(u),v(v),w(w){}   
    }e[N];        
    struct E 
    { 
        int u,op; 
        E(int u=0,int op=0):u(u),op(op){}  
    };       
    void Modify(int l,int r,int now,int L,int R,int id) 
    {
        if(l>=L&&r<=R) 
        {   
            G[now].push_back(id);   
            return; 
        }  
        int mid=(l+r)>>1;   
        if(L<=mid)   Modify(l,mid,lson,L,R,id);   
        if(R>mid)    Modify(mid+1,r,rson,L,R,id);      
    }      
    void solve(int l,int r,int now,ll pre) 
    {                        
        stack<E>S;  
        for(int i=0;i<G[now].size();++i) 
        {  
            int id=G[now][i];            
            int u=e[id].u,v=e[id].v,w=e[id].w;        
            int _new=id+n;   
            if(LCT::findroot(u)!=LCT::findroot(v)) 
            {      
                LCT::t[_new].w=w;    
                LCT::Link(u,_new);   
                LCT::Link(_new,v);    
                pre+=1ll*w;              
                S.push(E(_new,0));   
            }
            else 
            { 
                LCT::split(u,v);   
                if(LCT::t[v].maxx>w) 
                {    
                    pre=pre-LCT::t[v].maxx+w;   
                    int tmp=LCT::t[v].id;    
                    LCT::cut(tmp,e[tmp-n].u); 
                    LCT::cut(tmp,e[tmp-n].v);         
                    LCT::t[_new].w=w;   
                    LCT::Link(u,_new);   
                    LCT::Link(_new,v);       
                    S.push(E(tmp,1));   
                    S.push(E(_new,0));       
                }
            }
        }     
        if(l==r)       printf("%lld
    ",pre+1);   
        else 
        {           
            int mid=(l+r)>>1;   
            if(l<=mid)   solve(l,mid,lson,pre);    
            if(r>mid)    solve(mid+1,r,rson,pre);   
        }    
        while(!S.empty()) 
        {          
            E pp=S.top(); S.pop();  
            if(pp.op==0) 
            {  
                LCT::cut(pp.u,e[pp.u-n].u);  
                LCT::cut(pp.u,e[pp.u-n].v);  
            } 
            else
            {      
                LCT::t[pp.u].w=e[pp.u-n].w;  
                LCT::Link(pp.u,e[pp.u-n].u); 
                LCT::Link(pp.u,e[pp.u-n].v);  
            }
        }
    }
    #undef lson 
    #undef rson  
    int main()
    {
        // setIO("input");
        int i,j,m;     
        scanf("%d",&n);     
        for(i=1;i<n;++i) 
        { 
            int u,v,w;                   
            scanf("%d%d%d",&u,&v,&w);            
            e[i]=edge(u,v,w);    
            Modify(1,RM,1,1,RM,i);     
        }
        scanf("%d",&m);    
        for(i=1;i<=m;++i) 
        {
            int u,v,w,l,r;    
            scanf("%d%d%d%d%d",&u,&v,&w,&l,&r), e[n+i-1]=edge(u,v,w), Modify(1,RM,1,l,r,n+i-1);   
        }           
        solve(1,RM,1,0ll);   
        return 0;
    }
    

      

  • 相关阅读:
    Advanced Installer文件和文件夹页面中的临时文件操作
    celery使用方法
    网站高并发之道
    大话程序猿眼里的高并发
    StringTokenizer类的使用
    linux下查看最消耗CPU、内存的进程
    分享10条PHP性能优化的小技巧,帮助你更好的用PHP开发:
    json 除去转义字符以及查看json错误
    关于 redis、memcache、mongoDB 的对比
    QPS 与 TPS 简介
  • 原文地址:https://www.cnblogs.com/guangheli/p/11941413.html
Copyright © 2020-2023  润新知