列表

详情


NC20380. [SDOI2015]道路修建

描述

某国有2N个城市,这2N个城市构成了一个2行N列的方格网。
现在该国政府有一个旅游发展计划,这个计划需要选定L、R两列(L ≤ R),修建若干条专用道路,使得这两列之间(包括这两列)的所有2(R-L+1)个城市中每个城市可以只通过专用道路就可以到达这2(R-L+1)个城市中的任何一个城市。
这种专用道路只能在同一行相邻两列的城市或者同一列的两个城市之间修建,且修建需要花费一定的费用。
由于该国政府决定尽量缩减开支,因此政府决定,选定L、R后,只修建2(R-L+1)-1条专用道路,使得这些专用道路构成一个树结构。
现在你需要帮助该国政府写一个程序,完成这个任务。具体地,该任务包含M个操作,每个操作的格式如下: 
1.C x0 y0 x1 y1 w:由于重新对第x0行第y0列的城市和第x1行第y1列的城市之间的情况进行了考察,它们之间修建一条专用道路的花费变成了w;
2.Q L R:若政府选定的两列分别为L、R,询问政府的最小开支。

输入描述

第一行,两个整数N、M。
第二行,N-1个整数,其中第i个整数表示初始时第1行第i列的城市和第1行第i+1列的城市之间修建一条专用道路的费用。
第三行,N-1个整数,其中第i个整数表示初始时第2行第i列的城市和第2行第i+1列的城市之间修建一条专用道路的费用。
第四行,N个整数,其中第i个整数表示初始时第1行第i列的城市和第2行第i列的城市之间修建一条专用道路的费用。
接下来的M行,每行一个操作。

输出描述

对于每个询问操作,输出一行,表示你计算出的政府的最小开支。

示例1

输入:

3 3
1 2
2 1
3 1 2
Q 1 3
C 1 2 2 2 3
Q 2 3

输出:

7
5

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 147ms, 内存消耗: 6092K, 提交时间: 2020-02-19 14:55:52

#include<bits/stdc++.h>
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
const int MX=6e4+9;
int n,m,row[2][MX],clm[MX];
char order[2];
struct node{
    int l,r,cnt,sum;
    int l_val,r_val,l_max,r_max,row_max;
    void init(int pos){
        l=r=pos,cnt=1,row_max=0;
        sum=l_max=r_max=l_val=r_val=clm[pos];
    }
    friend inline node operator+(const node &L,const node &R){
        node ret;
        ret.l=L.l,ret.r=R.r;
        ret.row_max=max(max(row[0][L.r],row[1][L.r]),max(L.row_max,R.row_max));
        int del=max(max(row[0][L.r],row[1][L.r]),max(L.r_max,R.l_max));
        ret.sum=row[0][L.r]+row[1][L.r]+L.sum+R.sum-del;
        ret.cnt=L.cnt+R.cnt;
        ret.l_val=L.l_val,ret.r_val=R.r_val;
        ret.l_max=L.l_max,ret.r_max=R.r_max;
        if( L.r_val==del ){
            ret.cnt--;
            if( L.cnt==1 ){
                ret.l_val=R.l_val;
                ret.l_max=max(max(row[0][L.r],row[1][L.r]),max(L.row_max,R.l_max));
            }
        }
        else if( R.l_val==del ){
            ret.cnt--;
            if( R.cnt==1 ){
                ret.r_val=L.r_val;
                ret.r_max=max(max(row[0][L.r],row[1][L.r]),max(R.row_max,L.r_max));
            }
        }
        return ret;
    }
}t[MX<<2];

void build(int k,int l,int r){
    if( l==r ){
        t[k].init(l);
        return ;
    }
    int mid=(l+r)>>1;
    build(lson);
    build(rson);
    t[k]=t[k<<1]+t[k<<1|1];
}

void update_row(int k,int l,int r,int pos){
    int mid=(l+r)>>1;
    if( mid==pos ){
        t[k]=t[k<<1]+t[k<<1|1];
        return;
    }
    if( pos<=mid )
        update_row(lson,pos);
    else
        update_row(rson,pos);
    t[k]=t[k<<1]+t[k<<1|1];
}

void update_clm(int k,int l,int r,int pos){
    if( l==r ){
        t[k].init(pos);
        return ;
    }
    int mid=(l+r)>>1;
    if( pos<=mid )
        update_clm(lson,pos);
    else
        update_clm(rson,pos);
    t[k]=t[k<<1]+t[k<<1|1];
}

node que(int k,int l,int r,int L,int R){
    if( L<=l && r<=R )
        return t[k];
    int mid=(l+r)>>1;
    if( R<=mid )
        return que(lson,L,R);
    if( L>mid )
        return que(rson,L,R);
    else
        return que(lson,L,R)+que(rson,L,R);
}

int main()
{
    //freopen("input.txt","r",stdin);
    scanf("%d %d",&n,&m);
    for( int i=1 ; i<=n-1 ; i++ )
        scanf("%d",&row[0][i]);
    for( int i=1 ; i<=n-1 ; i++ )
        scanf("%d",&row[1][i]);
    for( int i=1 ; i<=n ; i++ )
        scanf("%d",&clm[i]);
    build(1,1,n);
    while( m-- ){
        scanf("%s",order);
        int x1,x2,y1,y2,w,l,r;
        if( order[0]=='C' ){
            scanf("%d %d %d %d %d",&x1,&y1,&x2,&y2,&w);
            if( x1==x2 ){
                if( y1>y2 )
                    swap(y1,y2);
                row[x1-1][y1]=w;
                update_row(1,1,n,y1);
            }
            else{
                clm[y1]=w;
                update_clm(1,1,n,y1);
            }
        }
        else{
            scanf("%d %d",&l,&r);
            printf("%d\n",que(1,1,n,l,r).sum);
        }
    }
    return 0;
}


C++(g++ 7.5.0) 解法, 执行用时: 269ms, 内存消耗: 17208K, 提交时间: 2023-01-12 19:21:53

#include <bits/stdc++.h>
#define val sum
#define rp mxr
#define lp mxl
#define int long long

const int N = 6e4+1;

int mp[3][N];
int mp1[N];
int n,m;

struct node{
	int l,r;
	int mxl,mxr;
	int id;
	int mx;
	int sum=0;
};

node tree[N<<2];

int querymx(int u, int x, int y){
	if(x>y) return 0;
	if(tree[u].l>=x&&tree[u].r<=y) return tree[u].mx;
	int minn=-1;
	if(tree[u<<1].r>=x) minn=querymx(u<<1,x,y);
	if(tree[u<<1|1].l<=y) minn=std::max(querymx(u<<1|1,x,y),minn);
	return minn;
}

void update(node &u,node l,node r,int mid){
    u.l=l.l,u.r=r.r;
    u.val=l.val+r.val+mp[1][mid]+mp[2][mid];
    u.mx=std::max(std::max(l.mx,r.mx),std::max(mp[1][mid],mp[2][mid]));
    int mx=std::max(querymx(l.id,l.rp,mid),querymx(r.id,mid+1,r.lp-1)),tmp=std::max(mp1[l.rp],mp1[r.lp]);   
    if(tmp<=mx)u.val-=mx,u.lp=l.lp,u.rp=r.rp;
    else if(tmp==mp1[l.rp])u.val-=tmp,u.lp=(l.lp==l.rp?r.lp:l.lp),u.rp=r.rp;
    else u.val-=tmp,u.lp=l.lp,u.rp=(r.rp==r.lp?l.rp:r.rp);
}

void build(int u, int l, int r){
	tree[u].l=l,tree[u].r=r;
	tree[u].id=u;
	if(l==r){
		tree[u].mxl=tree[u].mxr=l;
		tree[u].mx=std::max(mp[1][l],mp[2][l]);
		tree[u].sum=mp1[l];
		return;
	}
	int mid=l+r>>1;
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
	update(tree[u],tree[u<<1],tree[u<<1|1],mid);
}

void change(int u, int y){
	if(tree[u].l==tree[u].r){
		tree[u].sum=mp1[y];
		tree[u].mx=std::max(mp[1][y],mp[2][y]);
		return;
	}
	int mid=tree[u].l+tree[u].r>>1;
	if(y<=mid) change(u<<1,y);
	else change(u<<1|1,y);
	update(tree[u],tree[u<<1],tree[u<<1|1],mid);
}

node query(int u, int x, int y){
	if(tree[u].l==x&&tree[u].r==y) return tree[u];
	int mid=tree[u].l+tree[u].r>>1;
	if(y<=mid) return query(u<<1,x,y);
	else if(x>mid) return query(u<<1|1,x,y);
	node l=query(u<<1,x,mid),r=query(u<<1|1,mid+1,y),res;
	l.id=u<<1,r.id=u<<1|1,res.id=u;
	update(res,l,r,mid);
	return res;
}

signed main()
{
	std::ios::sync_with_stdio(0);
	std::cin.tie(0),std::cout.tie(0);
	
	std::cin >> n >> m;
	
	for(int i=1; i<=2; i++){
		for(int j=1; j<n; j++) std::cin >> mp[i][j];
	}
	
	for(int i=1; i<=n; i++) std::cin >> mp1[i];
	build(1,1,n);
	
	while(m--){
		char op;
		std::cin >> op;
		if(op=='Q'){
			int x,y;
			std::cin >> x >> y;
			std::cout << query(1,x,y).sum << '\n';
		}
		else{
			int a,b,c,d,e;
			std::cin >> a >> b >> c >> d >> e;
			if(a==c){
				if(b>d) mp[a][d]=e,change(1,d);
				else mp[a][b]=e,change(1,b);
			}
			else{
				mp1[b]=e;
				change(1,b);
			}
		}
	}
	
	return 0;
}

C++(clang++11) 解法, 执行用时: 95ms, 内存消耗: 6008K, 提交时间: 2021-02-15 09:04:31

#include <bits/stdc++.h>
using namespace std;
#define N 60005
#define mid ((l+r)>>1)
int a,b,c,d,e,n,m,v[N][3];char o[5];
struct nod{int l,r,lm,rm,ls,rs,am,ans,cnt;void init(int x){lm=rm=ls=rs=ans=v[x][2];cnt=1;am=0;}}s[N*4];
nod merge(nod x,nod y)
{
    nod z;z.l=x.l;z.r=y.r;
    int mxh=max(v[x.r][0],v[x.r][1]),mx=max(max(x.rm,y.lm),mxh);
    z.ans=x.ans+y.ans+v[x.r][0]+v[x.r][1]-mx;z.am=max(max(x.am,y.am),mxh);z.cnt=x.cnt+y.cnt;
    if(mx==x.rs&&x.cnt==1) z.lm=max(x.am,max(y.lm,mxh)),z.rm=y.rm,z.ls=y.ls,z.rs=y.rs,z.cnt--;
    else if(mx==y.ls&&y.cnt==1) z.lm=x.lm,z.rm=max(y.am,max(mxh,x.rm)),z.ls=x.ls,z.rs=x.rs,z.cnt--;
    else z.lm=x.lm,z.rm=y.rm,z.ls=x.ls,z.rs=y.rs,z.cnt-=(mx==x.rs||mx==y.ls);
    return z;
}
void bud(int x,int l,int r)
{
    if(l==r){s[x].init(l);s[x].l=l;s[x].r=r;return;}
    bud(x*2,l,mid);bud(x*2+1,mid+1,r);s[x]=merge(s[x*2],s[x*2+1]);
}
void upd(int x,int l,int r,int p)
{
    if(l==r){s[x].init(l);return;}
    if(p<=mid) upd(x*2,l,mid,p);else upd(x*2+1,mid+1,r,p);s[x]=merge(s[x*2],s[x*2+1]);
}
nod que(int x,int l,int r,int b,int e)
{
    if(b<=l&&r<=e) return s[x];
    if(e<=mid) return que(x*2,l,mid,b,e);if(b>mid) return que(x*2+1,mid+1,r,b,e);
    return merge(que(x*2,l,mid,b,e),que(x*2+1,mid+1,r,b,e));
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<n;i++) scanf("%d",&v[i][0]);
    for(int i=1;i<n;i++) scanf("%d",&v[i][1]);
    for(int i=1;i<=n;i++) scanf("%d",&v[i][2]);
    bud(1,1,n);
    for(int i=1;i<=m;i++)
    {
        scanf("%s",o);
        if(o[0]=='Q') scanf("%d%d",&a,&b),printf("%d\n",que(1,1,n,a,b).ans);
        else
        {
            scanf("%d%d%d%d%d",&a,&b,&c,&d,&e);if(b>d) swap(b,d);
            if(a!=c) v[b][2]=e,upd(1,1,n,b);else v[b][a-1]=e,upd(1,1,n,b);
        }
    }
}

上一题