BZOJ3995:道路修建(线段树维护MST)

传送门

题意:
给一张2×n的网格图,只有相邻的点连了边,支持询问区间的最小生成树,以及修改边权。

题解:线段树。
%%%PoPoQQQ : http://blog.csdn.net/popoqqq/article/details/45080183

#include<bits/stdc++.h>
using namespace std;
struct IO{
    streambuf *ib,*ob;
    inline void init(){
        ios::sync_with_stdio(false);
        cin.tie(NULL);cout.tie(NULL);
        ib=cin.rdbuf();ob=cout.rdbuf();
    }
    inline int read(){
        char ch=ib->sbumpc();int i=0,f=1;
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
        while(isdigit(ch)){i=(i+(i<<2)<<1)+ch-'0';ch=ib->sbumpc();}
        return i*f;
    }
    inline void W(long long x){
        static int buf[50];
        if(!x){ob->sputc('0');ob->sputc('\n');return;}
        if(x<0){ob->sputc('-');x=-x;}
        while(x){buf[++buf[0]]=x%10;x/=10;}
        while(buf[0])ob->sputc(buf[buf[0]--]+'0');
        ob->sputc('\n');
    }
}io;

const int Maxn=3e5+50;
int n,m,v[3][Maxn];
struct node{
    node *lc,*rc;
    int sum,posl,posr,cntline,mxl,mxr,mxall;
    inline void upt(int pos,node *x,node *y){
        int mx=max(v[1][pos],max(v[2][pos],max(x->mxr,y->mxl)));
        mxall=max(x->mxall,max(y->mxall,max(v[1][pos],v[2][pos])));
        cntline=x->cntline+y->cntline;
        if(mx==x->mxr){
            sum=x->sum+y->sum-x->mxr+v[1][pos]+v[2][pos];
            posr=y->posr;mxr=y->mxr;
            if(v[0][x->posr]==x->mxr){
                cntline--;
                if(x->cntline==1){
                    posl=y->posl;
                    mxl=max(x->mxall,max(y->mxl,max(v[1][pos],v[2][pos])));
                }
                else posl=x->posl,mxl=x->mxl;
            }
            else posl=x->posl,mxl=x->mxl;
        }
        else if(mx==y->mxl){
            sum=x->sum+y->sum-y->mxl+v[1][pos]+v[2][pos];
            posl=x->posl;mxl=x->mxl;
            if(v[0][y->posl]==y->mxl){
                cntline--;
                if(y->cntline==1){
                    posr=x->posr;
                    mxr=max(y->mxall,max(x->mxr,max(v[1][pos],v[2][pos])));
                }
                else posr=y->posr,mxr=y->mxr;
            }
            else posr=y->posr,mxr=y->mxr;
        }
        else {
            sum=x->sum+y->sum+(mx==v[1][pos]?v[2][pos]:v[1][pos]);
            posl=x->posl;posr=y->posr;
            mxl=x->mxl;mxr=y->mxr;
        }
    }
}Pool[Maxn],*pool=Pool,*null=Pool;
inline node* newnode(){
    ++pool;pool->lc=pool->rc=null;
    return pool;
}
struct SegmentTree{
    node *rt,*que[Maxn];
    int tail,rpos[Maxn];
    SegmentTree():rt(null){}
    inline void build(node *&now,int l,int r){
        now=newnode();
        if(l==r){
            now->sum=now->mxl=now->mxr=v[0][l];
            now->posl=now->posr=l;
            now->cntline=1;
            return;
        }
        int mid=(l+r)>>1;
        build(now->lc,l,mid);
        build(now->rc,mid+1,r);
        now->upt(mid,now->lc,now->rc);
    }
    inline void findpos(node *now,int l,int r,int L,int R){
        if(L<=l&&r<=R){que[++tail]=now;rpos[tail]=r;return;}
        int mid=(l+r)>>1;
        if(L<=mid)findpos(now->lc,l,mid,L,R);
        if(R>mid)findpos(now->rc,mid+1,r,L,R);
    }
    inline int query(int L,int R){
        tail=0;
        findpos(rt,1,n,L,R);
        if(tail==1)return que[tail]->sum;
        node tmp;tmp.upt(rpos[1],que[1],que[2]);
        for(int i=2;i<tail;i++){
            node tmp2=tmp;
            tmp.upt(rpos[i],&tmp2,que[i+1]);
        }
        return tmp.sum;
    }
    inline void modify(node *&now,int l,int r,int pos){
        if(l==r){
            now->sum=now->mxl=now->mxr=v[0][l];
            now->posl=now->posr=l;
            now->cntline=1;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)modify(now->lc,l,mid,pos);
        else modify(now->rc,mid+1,r,pos);
        now->upt(mid,now->lc,now->rc);
    }
}ST;

int main(){
    io.init();n=io.read(),m=io.read();
    for(int i=1;i<n;i++)v[1][i]=io.read();
    for(int i=1;i<n;i++)v[2][i]=io.read();
    for(int i=1;i<=n;i++)v[0][i]=io.read();
    ST.build(ST.rt,1,n);
    for(int i=1;i<=m;i++){
        static char ch[2];
        cin>>(ch+1);
        if(ch[1]=='Q'){
            int l=io.read(),r=io.read();
            io.W(ST.query(l,r));
        }
        else{
            int r1=io.read(),c1=io.read(),r2=io.read(),c2=io.read();
            if(r1==r2){
                if(c1>c2)swap(c1,c2);
                v[r1][c1]=io.read();
                ST.modify(ST.rt,1,n,c2);
            }
            else{
                v[0][c1]=io.read();
                ST.modify(ST.rt,1,n,c1);
            }
        }
    }
}
    原文作者:道路修建问题
    原文地址: https://blog.csdn.net/qq_35649707/article/details/78149358
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞