E-希望(線段樹加01揹包)

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

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章