https://ac.nowcoder.com/acm/contest/3800/B
题意:给你n个数,k能量,m种区间,区间内可以删除一个数但需要消耗能量,如何使总和最大。
解法:线段树维护每个数的最小花费的能量,如何对可删除的数进行删与不删两种选择,就是01背包问题。
//#include <bits/stdc++.h>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <iostream>
#include <algorithm>
#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdio.h>
#include <queue>
#include <stack>;
#include <map>
#include <set>
#include <ctype.h>
#include <string.h>
#include <vector>
#define ME(x , y) memset(x , y , sizeof(x))
#define SF(n) scanf("%d" , &n)
#define rep(i , n) for(int i = 0 ; i < n ; i ++)
#define INF 0x3f3f3f3f
#define mod 1000000007
#define PI acos(-1)
using namespace std;
typedef long long ll ;
const int N = 100009;
int val[N] , v[N] , w[N] , dp[509];
struct node{
int l , r , val , tag;
}tree[N << 2];
void build(int l , int r , int root)
{
tree[root].l = l , tree[root].r = r , tree[root].val = INF ;
if(l == r) return ;
int mid = (l + r) >> 1 ;
build(l , mid , root*2);
build(mid+1 , r , root*2+1);
}
void down(int root)
{
tree[root*2].val = min(tree[root*2].val , tree[root].val);
tree[root*2+1].val = min(tree[root*2+1].val , tree[root].val);
}
void update(int l , int r , int val , int root)//区间更新
{
if(tree[root].l >= l && tree[root].r <= r)
{
tree[root].val = min(val , tree[root].val);
return ;
}
down(root);
int mid = (tree[root].l + tree[root].r) >> 1;
if(l <= mid)
update(l , r , val , root*2);
if(r > mid)
update(l , r , val , root*2+1);
}
int ask(int x , int root)//单点查询
{
if(tree[root].l == tree[root].r)
{
return tree[root].val ;
}
down(root);
int mid = (tree[root].l + tree[root].r) >> 1 ;
if(x <= mid)
{
return ask(x , root*2);
}
else
{
return ask(x , root*2+1);
}
}
int main()
{
/*#ifdef ONLINE_JUDGE
#else
freopen("D:/c++/in.txt", "r", stdin);
freopen("D:/c++/out.txt", "w", stdout);
#endif*/
int n , k , m , sum = 0;
scanf("%d%d%d" , &n , &k , &m);
for(int i = 1 ; i <= n ; i++)
{
scanf("%d" , &val[i]);
sum += val[i];
}
build(1 , n , 1);
for(int i = 0 ; i < m ; i++)
{
int l , r , x ;
scanf("%d%d%d" , &l ,&r , &x);
update(l , r , x , 1);
}
int cnt = 0 ;
for(int i = 1 ; i <= n ; i++)
{
if(val[i] < 0)
{
v[cnt] = -val[i];
w[cnt] = ask(i , 1);
cnt++;
}
}
for(int i = 0 ; i < cnt ; i++)
{
for(int j = k ; j >= w[i] ; j--)
{
dp[j] = max(dp[j] , dp[j-w[i]]+v[i]);
}
}
cout << sum + dp[k] << endl ;
return 0 ;
}