ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

CF1707A题解

2022-09-10 22:01:03  阅读:151  来源: 互联网

标签:二分 int 题解 元素 选取 IQ CF1707A include


原题

CF1707A Doremy's IQ


思路概述

题意分析

给定一个长度为 \(n\) 的序列 \(a_i\) 和一个整数 \(q\),对于序列中的每个元素按顺序遍历并选数,每个元素可选可不选,但如果出现选取了 \(a_i>q\) 的情况,\(q\) 减去 \(1\),在保证选取元素数量最多的前提下输出选数情况。

思路分析

最先看题以为是背包,故尝试定义状态并写递推关系式。但是由于是按顺序选数,所以会存在选了当前的 \(a_i>q\),导致往后没法选出最多元素的情况,即有后效性,所以该方法不可行。

通过甚至不用简单分析可以得到一种“次优解”思路,即只选取 \(a_i≤q\) 这种情况的元素。这样可以保证在\(q\) 不减少的前提下选取最多元素。

但是上述思路有一个问题,即部分情况可以先选取若干个 \(a_i>q\) 的元素,因为往后的元素过小而对之后选取元素不造成影响,例如以下数据:

\[\{ a_i\}=\{5,1,1,1,1\},q=4 \]

所以我们可以采取以下策略:对给定的数列,在前半段采取只选取 \(a_i≤q\) 的做法,在后半段采取选取所有元素的做法。只要能恰当求出两种策略的使用区间,就可以选取最多元素。

在此策略下,前半段区间越长,\(q\) 最后的值必然越大,而选取元素是数量必然越少。这种单调性意味着本题可以采用二分答案的算法,在主函数二分出两种选取方法的区间,在检验函数中检验当前划分是否可行。最后使得前半段区间尽可能短,即得到正确答案。


算法实现

关于二分的开闭区间问题

由于本题数据都是整数,所以务必注意二分过程中区间开闭问题。

笔者采用的是左闭右开区间,所以在二分过程中,变量 \(r\) 始终指向区间最右端右边第一个元素,所以在判定时保证 \(l<r\) 并且在调整区间左端点时将 \(l\) 调整为 \(mid+1\),调整右端点时将 \(r\) 调整为 \(mid\)。左开右闭区间同理。

关于检查函数

检验函数编写很简单,但是注意当前划分可行的条件是 \(IQ_{final}≥0\) 而非 \(IQ_{final}>0\)。


AC code

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<queue>
#include<set>
#include<ctime>
#define RI register int
using namespace std;
const int maxn=1e5+10;
int T,n,q,pos;
int a[maxn];
bool ans[maxn];
inline bool judge(int x);
int main()
{
	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	for(cin >> T;T;--T)
	{
		cin >> n >> q;
		memset(a,0,sizeof(a));memset(ans,0,sizeof(ans));pos=n+1;
		for(RI i=1;i<=n;++i) cin >> a[i];
		RI l=1,r=n+1;
		while(l<r)
		{
			RI mid=(l+r)>>1;
			if(judge(mid))
			{
				pos=mid;
				r=mid;
			}
			else l=mid+1;
		}
		for(RI i=1;i<pos;++i) ans[i]=(a[i]<=q);
		for(RI i=pos;i<=n;++i) ans[i]=1;
		for(RI i=1;i<=n;++i) printf("%d",ans[i]);
		putchar('\n');
	}
	return 0;
}
inline bool judge(int x)
{
	RI IQ=q;
	for(RI i=x;i<=n;++i) if(a[i]>IQ) --IQ;
	return (IQ>=0);
}

标签:二分,int,题解,元素,选取,IQ,CF1707A,include
来源: https://www.cnblogs.com/frkblog/p/16678473.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有