链接:https://ac.nowcoder.com/acm/contest/917/E
来源:牛客网
题目描述
水宝宝驾驶着毁灭号接近了勇者号舰桥。
他要使用毁灭号的等离子炮摧毁勇者号主控台。
但是操控等离子炮的程序出了点问题。等离子炮有n个操作信号,第i个操作信号的强度为b[i]。总体强度为各操作信号的强度之和。
由于有些信号太弱了了 (强度<0),水宝宝想把它们删除。但是水宝宝自己不会删除信号,所以他找来了同船的队友帮忙。
有 m位队友,第ii 位队友只会删除编号在 L[i] 和 R[i]之间的信号,且每删除一个信号,花费 C[i]格能量。飞船一共有 k格能量,问他在请队友删除完信号后,总体强度最大是多少。
注:本系列题不按难度排序哦
输入描述:
输入格式: 第一行包含三个正整数 n,k,m 第二行包含 n个正整数 b1,b2,⋯,bn,表示各信号的强度。 接下来 m 行,每行三个正整数Li,Ri,Ci,表示一个队友的属性。
输出描述:
输出格式: 输出一行一个整数,表示最大的信号强度
示例1
输入
复制
5 10 5 10 -2 -5 7 -10 1 1 5 2 4 10 4 4 12 3 4 10 1 5 15
输出
复制
5
说明
样例解释:花费10的代价除掉a[3],答案即为10+7-10-2=5
备注:
对于 100% 的数据,1≤n,m≤10^5;1≤k≤500;1≤C[i]≤500;1≤L[i]≤R[i]≤n;-10^9≤b[i]≤10^9
这题不看区间更新那是不是很像一个01背包的做法。最小花费最大容量,我们只需要把负的去掉尽量多就可以了。
难就难在如何区间更新?细细一想其实可以联想到线段树的区间更新,需要懒人标记,无奈自己线段树水平太差,打了半个小时没写出来,第二天又花了半个小时才做出来。。。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll inf=1e18;
ll sum[N*4],w[N],dp[600];
int flag[N*4],v[N];
int n,k,m,cnt;
struct node
{
int x,id;
}a[N];
void build(int id,int l,int r)
{
sum[id]=inf;
flag[id]=1;
if(l==r) return ;
int mid=l+r>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
void pushdown(int id,int l,int r)
{
if(flag[id])
{
sum[id<<1]=min(sum[id<<1],sum[id]);
sum[id<<1|1]=min(sum[id<<1|1],sum[id]);
}
}
void up(int id,int l,int r,int ql,int qr,ll val)
{
if(l==r)
{
sum[id]=min(sum[id],val);
flag[id]=1;
return ;
}
if(ql<=l&&r<=qr)
{
if(flag[id])
{
sum[id]=min(sum[id],val);
return ;
}
}
pushdown(id,l,r);
int mid=l+r>>1;
if(ql<=mid) up(id<<1,l,mid,ql,qr,val);
if(qr>mid) up(id<<1|1,mid+1,r,ql,qr,val);
if(sum[id<<1]!=inf&&sum[id<<1|1]!=inf&&sum[id<<1]==sum[id<<1|1]) flag[id]=1,sum[id]=sum[id<<1];
else flag[id]=0,sum[id]=inf;
}
ll qu(int id,int l,int r,int pos)
{
if(l==r) return sum[id];
if(flag[id]) return sum[id];
pushdown(id,l,r);
int mid=l+r>>1;
if(pos<=mid) return qu(id<<1,l,mid,pos);
else return qu(id<<1|1,mid+1,r,pos);
}
int main()
{
cin>>n>>k>>m;
build(1,1,n);
ll sum=0;
for(int i=1;i<=n;i++)
{
ll x;
scanf("%lld",&x);
sum+=x;
if(x<0) a[++cnt].x=x,a[cnt].id=i;
}
for(int i=1;i<=m;++i)
{
int l,r,vv;
scanf("%d%d%d",&l,&r,&vv);
up(1,1,n,l,r,vv);
}
int inde=0;
for(int i=1;i<=cnt;++i)
{
ll num=qu(1,1,n,a[i].id);
if(num==1e9+10) continue;
v[++inde]=-a[i].x;
w[inde]=num;
}
for(int i=1;i<=inde;++i)
for(int j=k;j-w[i]>=0;j--)
dp[j]=max(dp[j],dp[j-w[i]]+v[i]);
printf("%lld\n",sum+dp[k]);
}