[算进] 防线 题解

题目地址

ACwing题目地址

Solution

套路题。不会做只是我没见过这个套路而已

突破口: 但是整条防线上也最多只有一个位置有奇数个防具

我们知道一个原理 :偶+偶=偶,奇+偶=奇。

又因为我们可以快速算出一个前缀和,比如说算出 x 之前有多少个防具,(用等差数列的一些公式快速O(1)算出,因为有 n 个等差数列所以算一次前缀和的的时间是 O(n))。记 x 的前缀和为 S(x)

我们又发现如果答案(奇数)在 p 这个位置,x[0,p) S(x) 都是偶数,而 x[p,R) S(x) 都是奇数(R 是右边界)。这样就有了一个分界点,可以二分了。二分答案的位置。

时间复杂度 O(nlogL) (n<=200000,L<=2311),可以过。

Code

Talk is cheap.Show me the code.

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
using namespace std;
inline int read() {
	int x=0,f=1; char ch=getchar();
	while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
	while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
	return x * f;
}
const int N = 200007;
int n,pos,ans;
int S[N],E[N],D[N];
int check(int x) {
	int res = 0, sum;
	for(int i=1;i<=n;++i) {
		if(x < S[i]) sum = 0;
		else sum = ((min(E[i],x)-S[i])/D[i]) + 1;
		res += sum;
	}
	return res;
}
void work() {
	int l = 1, r = -INF, mid, tmp;
	n = read();
	for(int i=1;i<=n;++i) S[i] = read(), E[i] = read(), D[i] = read(), r = max(r,E[i]);
	pos = -1;
	while(l <= r) {
		mid = (l+r)>>1;
		if(check(mid) & 1) {
			pos = mid, ans = check(mid) - check(mid-1);
			r = mid - 1;
		} else l = mid + 1;
	}
	if(pos==-1) puts("There's no weakness.");
	else printf("%d %d\n",pos,ans);
}
int main()
{
	int T = read();
	while(T--) work();
	return 0;
}

Summary

  • 这个题目让我学会了从奇偶性推导出单调性的套路

  • 让我学会了等差数列的一些小性质

posted @   基地AI  阅读(210)  评论(3编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示