• 【线段树】bzoj3995 [SDOI2015]道路修建


    线段树每个结点维护5个域:

    整个区间的MST。

    将两个左端点连通,两个右端点不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。

    将两个右端点连通,两个左端点不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。

    两个左端点不连通,两个右端点也不连通,整个区间内选择2*(r-l+1)-2条边的最小生成森林,有两个连通块。(就是上面一条线,下面一条线)

    两个左端点不连通,两个右端点也不连通,整个区间内选择2*(r-l+1)-3条边的最小生成森林,有3个连通块。

    合并时讨论5*5*2(两条夹缝里的横边是否都选择)种情况。

    /*每个结点维护5个域:左右完全连通,左连通右不连通,右连通左不连通,左右都不连通2,左右都不连通3*/
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 60001
    #define INF 1000000000
    int n,m,heng[2][N],zong[N];
    struct Node
    {
    	int z1y1,z1y0,z0y1,z0y02,z0y03;
    	void reset(){z1y1=z1y0=z0y1=z0y02=z0y03=INF;}
    }T[N<<2];
    inline void pushup(Node &rt,const Node &ls,const Node &rs,const int &r1,const int &l1,const int &l2)
    {
    	rt.reset();
    	
    	int MIN=min(heng[0][r1],heng[1][r1]),SUM=heng[0][r1]+heng[1][r1];
    	
    	/*z1y1+z1y1*/rt.z1y1=ls.z1y1+rs.z1y1+MIN;
    	if(l2>1)/*z1y1+z1y0*/rt.z1y0=ls.z1y1+rs.z1y0+MIN;
    	if(l2>1)/*z1y1+z0y1*/rt.z1y1=min(rt.z1y1,ls.z1y1+rs.z0y1+SUM);
    	/*z1y1+z0y02*/rt.z1y1=min(rt.z1y1,ls.z1y1+rs.z0y02+SUM);
    				  rt.z1y0=min(rt.z1y0,ls.z1y1+rs.z0y02+MIN);
    	if(l2>1)/*z1y1+z0y03*/rt.z1y0=min(rt.z1y0,ls.z1y1+rs.z0y03+SUM);
    	
    	if(l1>1)/*z1y0+z1y1*/rt.z1y1=min(rt.z1y1,ls.z1y0+rs.z1y1+SUM);
    	if(l1>1&&l2>1)/*z1y0+z1y0*/rt.z1y0=min(rt.z1y0,ls.z1y0+rs.z1y0+SUM);
    	/*z1y0+z0y1不合法*/
    	if(l1>1)/*z1y0+z0y02*/rt.z1y0=min(rt.z1y0,ls.z1y0+rs.z0y02+SUM);
    	/*z1y0+z0y03不合法*/
    	
    	if(l1>1)/*z0y1+z1y1*/rt.z0y1=ls.z0y1+rs.z1y1+MIN;
    	if(l1>1&&l2>1)/*z0y1+z1y0*/rt.z0y03=ls.z0y1+rs.z1y0+MIN;
    	if(l1>1&&l2>1)/*z0y1+z0y1*/rt.z0y1=min(rt.z0y1,ls.z0y1+rs.z0y1+SUM);
    	if(l1>1)/*z0y1+z0y02*/rt.z0y1=min(rt.z0y1,ls.z0y1+rs.z0y02+SUM),
    				  		  rt.z0y03=min(rt.z0y03,ls.z0y1+rs.z0y02+MIN);
    	if(l1>1&&l2>1)/*z0y1+z0y03*/rt.z0y03=min(rt.z0y03,ls.z0y1+rs.z0y03+SUM);
    	
    	/*z0y02+z1y1*/rt.z1y1=min(rt.z1y1,ls.z0y02+rs.z1y1+SUM);
    				  rt.z0y1=min(rt.z0y1,ls.z0y02+rs.z1y1+MIN);
    	if(l2>1)/*z0y02+z1y0*/rt.z1y0=min(rt.z1y0,ls.z0y02+rs.z1y0+SUM),
    						  rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z1y0+MIN);
    	if(l2>1)/*z0y02+z0y1*/rt.z0y1=min(rt.z0y1,ls.z0y02+rs.z0y1+SUM);
    	/*z0y02+z0y02*/rt.z0y02=ls.z0y02+rs.z0y02+SUM;
    				   rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z0y02+MIN);
    	if(l2>1)/*z0y02+z0y03*/rt.z0y03=min(rt.z0y03,ls.z0y02+rs.z0y03+SUM);
    	
    	if(l1>1)/*z0y03+z1y1*/rt.z0y1=min(rt.z0y1,ls.z0y03+rs.z1y1+SUM);
    	if(l1>1&&l2>1)/*z0y03+z1y0*/rt.z0y03=min(rt.z0y03,ls.z0y03+rs.z1y0+SUM);
    	/*z0y03+z0y1不合法*/
    	if(l1>1)/*z0y03+z0y02*/rt.z0y03=min(rt.z0y03,ls.z0y03+rs.z0y02+SUM);
    	/*z0y03+z0y03不合法*/
    }
    void buildtree(int rt,int l,int r)
    {
    	if(l==r)
    	  {
    	  	T[rt].z1y1=zong[l];
    	  	return;
    	  }
    	int m=(l+r>>1);
    	buildtree(rt<<1,l,m);
    	buildtree(rt<<1|1,m+1,r);
    	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
    }
    void update(int p,int v,int rt,int l,int r)
    {
    	if(l==r)
    	  {
    	  	zong[p]=v;
    	  	T[rt].z1y1=v;
    	  	return;
    	  }
    	int m=(l+r>>1);
    	if(p<=m) update(p,v,rt<<1,l,m);
    	else update(p,v,rt<<1|1,m+1,r);
    	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
    }
    void update(int p,int rt,int l,int r)
    {
    	if(l==r) return;
    	int m=(l+r>>1);
    	if(p<=m) update(p,rt<<1,l,m);
    	else update(p,rt<<1|1,m+1,r);
    	pushup(T[rt],T[rt<<1],T[rt<<1|1],m,m-l+1,r-m);
    }
    Node query(int ql,int qr,int rt,int l,int r)
    {
        if(ql<=l && r<=qr) return T[rt];
        int m=(l+r>>1);
        if(ql<=m && m<qr)
          {
            Node res;
            pushup(res,query(ql,qr,rt<<1,l,m),query(ql,qr,rt<<1|1,m+1,r),m,m-l+1,r-m);
            return res;
          }
        else if(ql<=m) return query(ql,qr,rt<<1,l,m);
        else return query(ql,qr,rt<<1|1,m+1,r);
    }
    int main()
    {
    //	freopen("bzoj3995.in","r",stdin);
    //	freopen("bzoj3995.out","w",stdout);
    	for(int i=1;i<=500000;++i);
    	scanf("%d%d",&n,&m);
    	for(int i=0;i<2;++i)
    	  for(int j=1;j<n;++j)
    	    scanf("%d",&heng[i][j]);
    	for(int i=1;i<=n;++i)
    	  scanf("%d",&zong[i]);
    	buildtree(1,1,n);
    //	printf("%d
    ",query(1,3,1,1,n).z1y1);
    //	printf("%d
    ",query(1,3,1,1,n).z1y0);
    //	printf("%d
    ",query(1,3,1,1,n).z0y1);
    //	printf("%d
    ",query(1,3,1,1,n).z0y02);
    //	printf("%d
    ",query(1,3,1,1,n).z0y03);
    	char op[3];
    	int x1,y1,x2,y2,val;
    	for(;m;--m)
    	  {
    	  	scanf("%s",op);
    	  	if(op[0]=='C')
    	  	  {
                scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&val);
                if(y1==y2) update(y1,val,1,1,n);
                else
                  {
                    if(y1>y2) swap(y1,y2);
                    heng[x1-1][y1]=val;
                    update(y1,1,1,n);
                    update(y2,1,1,n);
                  }
              }
            else
              {
              	scanf("%d%d",&y1,&y2);
              	printf("%d
    ",query(y1,y2,1,1,n).z1y1);
              }
    	  }
    	return 0;
    }
  • 相关阅读:
    kubectl命令行工具
    资源编排(YAML)
    vscode自定义vue模板代码
    vscode10个必装的插件
    【转】Android系统开篇
    Android应用资源分析(老罗链接整理)
    APK优化工具zipalign的详细介绍和使用
    Android中APK签名工具之jarsigner和apksigner详解
    Android反编译和二次打包
    python修饰器(装饰器)以及wraps
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/4638048.html
Copyright © 2020-2023  润新知