列表

详情


NC205068. 保卫家园

描述

为了抵御深渊的蔓延,被深渊毁掉家园的人们组建法兰不死队来镇压深渊。已知法兰不死队的最大编制为k,即队伍最多能有k人。有n个人想加入不死队,他们每人都有一个期望入伍时间s和退役时间t。入伍时间表示这个人如果要入伍的话只能在s时刻入伍。退役时间代表这个人可以在t时刻后退伍。因为战况严峻,所以队伍必须一直保持达到最大编制的状态。即队伍达到最大编制时候,队伍里有人可以退役的话,如果没有人来接替这个人的位置就不能退役。问最少有多少人没有进入法兰不死队的经历。
注:同一时刻,允许多个人一起入伍或者退伍,退伍时间要严格大于t 
该人是否入伍是你来决定的  即就算没达到最多编制人数k,到了某人的入伍时间,你可以选择不让他入伍

输入描述

第一行两个数n、k,分别表示有n个人想入伍,最大编制为k人。(1≤n≤106、1≤k≤n)
第二行开始每行两个数s、t 。(1≤s≤t≤106

输出描述

输出只有一行,表示最少有多少人没有入伍的经历。

示例1

输入:

3 2
1 9
1 2
3 4

输出:

0

示例2

输入:

3 2
1 9
1 2
2 4

输出:

1

说明:

第二个人和第三个人之中一定有一个人无法入伍

示例3

输入:

3 1
1 9
2 3
4 5

输出:

1

说明:

不让第一个人入伍的方案最优

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 615ms, 内存消耗: 26468K, 提交时间: 2020-06-23 15:27:26

#include <bits/stdc++.h>
using namespace std;

const int MAXN=1e6+10;
struct node{
    int s,e;
    bool operator < (const node a)const{
        return s==a.s?e<a.e:s<a.s;
    }
}arr[MAXN];
int n,k;
multiset<int> st;

int main(){
    scanf("%d%d",&n,&k);
    for(int i=0;i<n;i++)scanf("%d%d",&arr[i].s,&arr[i].e);
    sort(arr,arr+n);
    int res=0;
    for(int i=0;i<n;i++){
        if(!st.empty() && *st.begin()<arr[i].s)st.erase(st.begin());
        if(st.size()<k)st.insert(arr[i].e);
        else{
            res++;
            st.insert(arr[i].e);
            st.erase(--st.end());
        }
    }
    printf("%d",res);
    return 0;
}

C++11(clang++ 3.9) 解法, 执行用时: 1250ms, 内存消耗: 59344K, 提交时间: 2020-06-26 10:30:13

#include<bits/stdc++.h>
using namespace std;

const int maxn=1e6+10;

multiset<int> s;
vector<int> t[maxn];

int main()
{
	int n,k;
	scanf("%d%d",&n,&k);
	for( int i=1;i<=n;i++ )
	{
		int l,r;scanf("%d%d",&l,&r);
		t[l].push_back(r);
	}
	int ans=0;
	for( int i=1;i<=1e6;i++ )
	{
		while( !s.empty() && *s.begin()<i ) s.erase(s.begin());
		for( auto it:t[i] )
		{
			if( s.size()<k ) s.insert(it);
			else 
			{
				ans++;
				s.insert(it);
				s.erase(--s.end());
			}
		}
	}
	printf("%d\n",ans);
}

上一题