2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules) D. Fi

2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules)  D. Fi
2020-2021 ICPC, NERC, Southern and Volga Russian Regional Contest (Online Mirror, ICPC Rules)  D. Fi

  • 题意:有个长度为\(n\)的*,犯人在位置\(a\),cop在位置\(b\),你每次可以向左或者向右移动一个单位,或者选择不动并在原地放一个爆竹\(i\),爆竹\(i\)在\(s[i]\)秒后爆炸,cop每次向你的位置移动一个单位,你最终一定会被抓住(因为*是有限的),问你在被抓住前,最多能看到多少爆竹爆炸.
  • 题解:我们可以很容易算出最能放多少个爆竹不被cop抓住,和最晚被cop抓住的时间,然后对爆竹的爆炸时间排序,假如我们要放\(x\)个爆竹,那么很显然,最优的放法一定是在第一秒放\(s[x]\),第二秒放\(s[x-1]\),...,因为我们一定会放\(x\)个爆竹,所以爆炸所需时间长的我们要先放,后放的话可能被抓住时不会爆炸,有了这个贪心思路,接下来我们对爆炸数进行二分然后判断即可.
  • 代码:
#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 1e9 + 7;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}

int t;
int n,m,a,b;
int s[N];

bool check(int x,int lim){
	rep(i,1,x){
		if(i+s[x-i+1]>lim) return false;
	}
	return true;
}

int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>t;

	while(t--){
		cin>>n>>m>>a>>b;

		rep(i,1,m){
			cin>>s[i];
		}

		sort(s+1,s+1+m);

		int fin=b-1;  //when is caught
		int cnt=b-a-1;  //nums of firecrackers

		if(a>b){
			fin=n-b;
			cnt=a-b-1;
		}
		
		cnt=min(cnt,m);

		int l=0,r=cnt;

		while(l<r){
			int mid=(l+r+1)>>1;
			if(check(mid,fin)) l=mid;
			else r=mid-1;
		}
	
		cout<<l<<'\n';
		
	}

    return 0;
}
上一篇:RedHat下安装Telnet服务端及客户端远程连接配置


下一篇:统一代码风格工具——editorConfig