zoukankan      html  css  js  c++  java
  • 01背包(线段树维护最小花费)

    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 ;
    }
    
  • 相关阅读:
    知道这几 个正则表达式,能让你少写 1,000 行代码
    移除手机端a标签点击自动出现的边框和背景
    CSS 元素垂直居中的 6种方法
    当文本超出时出现省略号
    css清除select的下拉箭头样式
    设置透明边框
    js 输出语句document.write()及动态改变元素中内容innerHTML的使用
    LOCAL_EXPORT_××用法
    sprd测试系统跑vts
    C++ const用法
  • 原文地址:https://www.cnblogs.com/nonames/p/12152676.html
Copyright © 2011-2022 走看看