2022.9.16———HZOI【CSP-S开小灶5】游寄

Preface

Rank46/41

15pts+30pts=45pts

T1 乌鸦喝水, T2 kill

T1 

这个题的题意太坑人了,没说清楚,样例也水,导致我挂成这弔样

他的意思是,乌鸦一共飞m回合,遇到能喝的就喝,喝了一次之后每个水缸的水位都要下降

这乌鸦够nb的

直接爆扫有25pts,及时break55pts,用链表优化爆扫有95pts

不是你这区分度也太差了吧

正解是树状数组,但是我没写

我去写了迪神的暴力dp,加点优化,没有水的水缸就不要了,这样可以卡过。感觉和链表差不多,不清楚为什么这个可以过,可能与内存访问连续有关

T1
#include <iostream>
#include <cmath>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ ' '
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define N 100005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL), cerr.tie(NULL);}
/*
	二度理解错题意 
*/
int n, m, final_ans, mxd;
int w[N], a[N];
void work(){
	cin >> n >> m >> mxd;
	for (re i = 1 ; i <= n ; ++ i)
		cin >> w[i];
	for (re i = 1 ; i <= n ; ++ i)
		cin >> a[i];
	for (re i = 1 ; i <= n ; ++ i)
		w[i] = ceil((double)(mxd - w[i] + 1) / a[i]);
	/*for (re i = 1 ; i <= n ; ++ i)
		cerr << w[i] << _;
	cerr << '\n';*/
	for (re i = 1 ; i <= m ; ++ i){
		for (re j = 1 ; j <= n ; ++ j){
			// cerr << i << _ << j << '\n';
			if (w[j] <= 0){
				continue;
			}
			for (re k = 1 ; k <= n ; ++ k)
				w[k] --;
			final_ans ++;
		}
	}
	cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
    #ifdef IXINGMY
        FBI_OPENTHEDOOR(a);
    #endif
    Fastio_setup();
    work();
    return GMY;
}

T2 kill

首先需要明白一件事情:这n个人打的怪物在q数组中的下标是连续的。而且哪个人打哪个怪物,也就是打怪物的相对顺序,与人的相对顺序是相同的。比如第一个人打选出来的第一个怪物,第二个人打选出来的第二个怪物...

这个东西,我小证明一下,可能并不严谨

比如n=4m=5有:

1 2 3 4 5 6 7 8 9

其中粗体是怪物,斜体是人,又粗又斜的是人和怪物重合了,那个十分突出的是任务交付点

显然要打第24个怪物。假如说第一个人去打第一个怪物,显然是比 第一个人打怪物2,第二个人打怪物3.... 更劣的。

如果你问:“假如任务交付点左边只有一个怪物,而且在人1的左边呢?”

这个时候方案就变了呗。不可否认的是,选的怪物还是连续的。这个性质用于一会的『枚举起点』。

这个时候“哪个人打哪个怪物,也就是打怪物的相对顺序,与人的相对顺序是相同的。”就不证自明了。这个性质用于一会的『判断距离』。

然后考虑如何求解答案。

首先把p数组和q数组升序sort一下,因为他读入并没有保证有单调性。

因为问的是最晚的人所需时间,所以考虑二分最晚所需时间。

考虑check函数怎么写。

由于选择的怪物在q数组中的下标是连续的,所以我们只需要枚举第一个位置是谁,然后向后延伸n长判断是否打怪所需距离大于mid即可。

T2
#include <iostream>
#include <algorithm>
#define GMY (520&1314)
#define FBI_OPENTHEDOOR(x) freopen(#x ".in", "r", stdin), freopen(#x ".out", "w", stdout);
#define re register int
#define char_phi signed
#define MARK cout << "###"
#define MARKER "@@@"
#define LMARK "!!!~~~"
#define ZY " qwq "
#define _ ' '
#define Endl cout << '\n'
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
#define MAX(x, y) (((x) > (y)) ? (x) : (y))
#define ABS(x) (((x) < 0) ? (-(x)) : (x))
#define N 5005
using namespace std;
inline void Fastio_setup(){ios::sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL), cerr.tie(NULL);}
long long n, m, endplc, final_ans;
long long a[N], b[N];
inline char check(long long mid){
	int x = 1;
	for (re i = 1 ; i <= n ; ++ i, ++ x){
		while (x <= m and ABS(a[i]-b[x])+ABS(b[x]-endplc) > mid)
			x ++;
		if (x > m)
			return false;
	}
	return true;
}
void work(){
	cin >> n >> m >> endplc;
	for (re i = 1 ; i <= n ; ++ i)
		cin >> a[i];
	for (re i = 1 ; i <= m ; ++ i)
		cin >> b[i];
	sort(a+1, a+n+1); sort(b+1, b+m+1);
	long long LF(0), RT(1000000002), mid;
	while (LF <= RT){
		mid = (LF + RT) >> 1;
		if (check(mid) == true)
			RT = mid - 1, final_ans = mid;
		else 
			LF = mid + 1;
	}
	cout << final_ans << '\n';
}
// #define IXINGMY
char_phi main(){
    #ifdef IXINGMY
        FBI_OPENTHEDOOR(a);
    #endif
    Fastio_setup();
    work();
    return GMY;
}
posted @   char_phi  阅读(6)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
点击右上角即可分享
微信分享提示