鏈接: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]);
}