染色(简单)

15 篇文章 0 订阅

 

题干: 

本题保证 m 个区间两两不相交。

小 P 得到了一个长为 n 的序列,序列元素编号 1…n。小 P 想给这个序列的每个元素染上黑 白两种颜色之一,于是他就随便制定了一个染色方案。正当小 P 要染色时,小 A 批判道:“Naive!这个染色方案太难看了,你应该仔细分析染色的效果之后再动手。” 小 A 和小 P 一起分析序列的性质之后,得出两个结论:

  1. 序列中的第 i 个位置染成黑色会产生 bi 的美感,染成白色会产生 wi 的美感。
  2. 有些区间比较特殊,如果区间内的所有数都染成黑色会额外得到 ci 的美感;另一些区间则恰好相反,如果区间内的所有数都染成白色会额外得到 ci 的美感。

小 A 和小 P 想知道美感总和的最大值,请你帮他们求出这个值。

输入格式

第一行两个整数 n,m分别表示序列的长度和特殊区间的数量。

第二行 n 个整数 bi,表示每个位置染成黑色会得到的美感。

第三行 n 个整数 wi,表示每个位置染成白色会得到的美感。

接下来下 m 行,每行四个整数 ti,li,ri,ci。 ti=1 表示如果区间 [li,ri] 都被染成黑色会额外得到 ci 的美感, ti=2 则表示如果区间 [li,ri] 都被染成白色会额外得到 ci 的美感。

输出格式

输出一行一个整数,表示美感总和的最大值。

数据范围与约定

保证 0≤n,m≤3×10^5,1≤li≤ri≤n,−10^9≤wi,bi≤10^9,ti∈{1,2},1≤ci≤10^9 。

本题保证 m 个区间两两不相交。

Sample Input

5 2
1 2 2 4 3
0 -2 7 1 5
2 1 2 7
1 5 5 1

Sample Output

21

Sample Explain

第 44 个位置染成黑色,其余位置染成白色,得到美感总和为 0+(−2)+7+4+5+7=21。

分析:

简单动归,用map存放特殊区间相关数据,key为r(右界),value为数组,数组中存放l(左界)、c(额外分)、count(区间填同一色的总分,填何种颜色按照t的值判断),ans数组维护前i个元素染色的最高分。

转移方程为

ans[i]=max(ans[i-1]+b[i],ans[i-1]+w[i]);

ans[i]=max(ans[iter->second[0]-1]+iter->second[1]+iter->second[2],ans[i]); (i在r上的额外情况考虑)

题解:

#include"bits/stdc++.h"
using namespace std;
typedef long long ll;

int main(){
    ll n,m;
    cin>>n>>m;
    ll b[n+7];
    ll w[n+7];
    for(ll i=1;i<=n;++i){
        cin>>b[i];
    }
    for(ll i=1;i<=n;++i){
        cin>>w[i];
    }
    map<ll,vector<ll> > hashmap;
    map<ll,vector<ll> >::iterator iter;
    for(ll i=1;i<=m;++i){
        ll t,l,r,c;
        cin>>t>>l>>r>>c;
        vector<ll> v;
        v.push_back(l);
        v.push_back(c);
        ll count=0;
        if(t==1){
            for(ll j=l;j<=r;++j){
                count+=b[j];
            }
        }
        else{
            for(ll j=l;j<=r;++j){
                count+=w[j];
            }
        }
        v.push_back(count);
        hashmap.insert(make_pair(r,v));
    }
    ll ans[n+7];
    memset(ans,0,sizeof(ans));
    ans[1]=max(b[1],w[1]);
    iter=hashmap.find(1);
    if(iter!=hashmap.end()){
        ans[1]+=iter->second[1];
    }
    for(ll i=2;i<=n;++i){
        ans[i]=max(ans[i-1]+b[i],ans[i-1]+w[i]);
        iter=hashmap.find(i);
        if(iter!=hashmap.end()){
            ans[i]=max(ans[iter->second[0]-1]+iter->second[1]+iter->second[2],ans[i]);
        }
    }
    cout<<ans[n];
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值