ICPC North Central NA Contest 2017 D+E+F

本小妞迷上赌 提交于 2020-03-02 00:56:13

D. Smooth Array

根据题意,显然是长度为k的循环节,所以按数组下标对k的余数进行分组

问题转换为:k组元素,每组选择一个要变换为的数值w,其价值为本组元素与w相 同的个数,且k组数值w的和为S.

最终使(N − 总价值)最小,即修改次数最 少。

 

分K组做一下背包。c[i]为该组i出现的次数。f[i]为体积为i时的最大价值。g[i]为上一组元素,到i这个体积的最大f[]值,在本组背包更新后,用g更新f,因为相当于本组一点贡献都没有,f[i]都一定能打到g[i]的价值。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=5e3+7;
int a[maxn],f[maxn],c[maxn],g[maxn];
int main()
{
    int n,k,s;
    scanf("%d%d%d",&n,&k,&s);
    for(int i=0;i<n;i++) scanf("%d",&a[i]);
    memset(f,-0x3f,sizeof(f));
    f[0]=0;
    for(int i=0;i<k;i++){
        vector<int>tmp;
        memset(c,0,sizeof(c));
        memset(g,0,sizeof(g));
        for(int j=i;j<n;j+=k){
            if(c[a[j]]==0) tmp.push_back(a[j]);
            c[a[j]]++;
        }
        for(int j=0;j<=s;j++) g[j]=max((j?g[j-1]:0),f[j]);
        for(int j=s;j>=0;j--){
            f[j]+=c[0];
            for(auto it:tmp){
                if(it&&j>=it){
                    f[j]=max(f[j],f[j-it]+c[it]);
                }
            }
            f[j]=max(f[j],g[j]);
        }
    }
    printf("%d\n",n-f[s]);
    return 0;
}

E

F. Atlantis

题意:海平面每秒上涨1m,有n个地点,每个地点有t往返时间,h海拔高度,在来回过程中那个地点必须一直保持在海平面上。求最多能去几个地点

题解:

因为海拔越低越早被淹没,所以相同时间下,海拔低的地点应该优先去。

按海拔高低排序后,维护往返时间从大到小的任务优先队列,sum为完成已经队列里的人物的总时间。

若该地点需要的往返时间+sum<=海拔,说明该任务可做,直接放进队列;

否则,比较队列里最大的时间,如果此时任务的时间小于最大时间,替换任务。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+7;
priority_queue<ll>q;
struct node{
    int t,h;
    bool operator <(const node &b){
        return h<b.h;
    }
}a[maxn];
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d%d",&a[i].t,&a[i].h);
    sort(a+1,a+1+n);
    ll sum=0;
    for(int i=1;i<=n;i++){
        if(sum+a[i].t<=a[i].h){
            q.push(a[i].t);
            sum+=a[i].t;
        }
        else{
            if(!q.empty()&&q.top()>a[i].t){
                sum-=q.top();
                q.pop();
                q.push(a[i].t);
                sum+=a[i].t;
            }
        }
    }
    printf("%d\n",q.size());
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!