首页 > 其他分享 >P5133题解

P5133题解

时间:2024-01-19 15:35:15浏览次数:27  
标签:ch int 题解 P5133 mid 区间

P5133 tb148的客人

题目传送门

题解

唯一的一篇题解还是交错题的……

很简单的一个二分加差分题。

显然是二分答案,考虑检验。如果 \(2mid+1\ge n\),那么所有人可以自由去到任意位置,一定可行;否则,我们求出每个人可以去到的区间范围,并以此推出要满足这个人的限制,\(1\) 号需要在哪个区间内(这里我们只考虑顺时针 \(1-n\) 的情况,逆时针的话,把原数组翻转就可以了),\(mid\) 可行就等价于这些区间有交。我们可以把每个区间 \(+1\),最后检验是否有点被加了 \(n\) 次,这是简单的差分可以做到的。不过要注意,这题是在环上的,所以我们要判断一下区间的 \(l\) 是否大于 \(r\),若是,我们把原区间拆成 \([1,r]\) 和 \([l,n]\) 这两个,显然这两个区间不会有交,所以正确性得证。

事实上,还有一种用 set 的做法,大致就是递推出每一种结局的最优方案,但是代码实现起来细节会很多,此处略。

代码:

#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int s=0,m=0;char ch=getchar();
	while(!isdigit(ch)) {if(ch=='-')m=1;ch=getchar();}
	while( isdigit(ch)) s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
	return m?-s:s;
}
int n,a[1000005],b[1000005];
bool check(int mid) {
	if(mid*2+1>=n) return 1;
	for(int i=1;i<=n+1;i++) b[i]=0;
	for(int i=1;i<=n;i++) {
		int l=(i-mid-a[i]+1+n*2-1)%n+1,r=(i+mid-a[i]+1+n*2-1)%n+1;
		if(l<=r) b[l]++,b[r+1]--;
		else b[1]++,b[r+1]--,b[l]++,b[n+1]--;
	}
	for(int i=1,s=0;i<=n;i++)
		if((s+=b[i])==n) return 1;
	for(int i=1;i<=n+1;i++) b[i]=0;
	for(int i=1;i<=n;i++) {
		int l=(i-mid-a[n-i+1]+1+n*2-1)%n+1,r=(i+mid-a[n-i+1]+1+n*2-1)%n+1;
		if(l<=r) b[l]++,b[r+1]--;
		else b[1]++,b[r+1]--,b[l]++,b[n+1]--;
	}
	for(int i=1,s=0;i<=n;i++)
		if((s+=b[i])==n) return 1;
	return 0;
}
signed main() {
	cin>>n;
	for(int i=1;i<=n;i++)
		a[i]=read(); 
	int l=0,r=n,mid,ans;
	while(l<=r) {
		mid=(l+r)>>1;
		if(check(mid)) r=mid-1,ans=mid;
		else l=mid+1;
	}
	cout<<ans;
	return 0;
}

标签:ch,int,题解,P5133,mid,区间
From: https://www.cnblogs.com/operator-/p/17974765

相关文章

  • P3867题解
    P3867[TJOI2009]排列计数题目传送门题解\(k\)很小,不是分讨就是突破口。如果我们用这种方式生成排列:将\(1\)到\(n\)按顺序插入当前状态,那么你会发现当前的数\(x\)的插入被很大程度的限制住了,我们只需记录当前\(x-k\)到\(x-1\)的位置即可枚举出所有可能的下一状态,因......
  • P7312题解
    P7312[COCI2018-2019#2]Sunčanje题目传送门题解分类讨论的思想有点像P4169?要你对于每一个矩形,求是否存在编号比它大,与它有交的矩形。直接做需要用一个比较神仙的线段树用法,所以我们可以容斥:我们求出编号比它大,与它无交的矩形数量,最后与所有可能覆盖它的矩形共\(n-i\)个......
  • P6554题解
    P6554PromisesICan'tKeep题目传送门题解看题解都有些做烦了,就来发一篇。换根dp。第一遍dfs处理出\(Lef_u\)表示\(u\)子树内的叶子个数(包含自己),然后求出以\(1\)为根时的答案\(\sumLef_u*val_u\),注意特判根为叶子的情况。第二遍dfs大力换根就好了,从根\(u\)......
  • P9744题解
    P9744「KDOI-06-S」消除序列题目传送门题解记错时间错过模拟赛的sb来也。题目中的最关键信息就是\(a_i,b_i,c_i\ge0\),这意味着多做无用的操作一定不优,所以有:结论\(1\):优先进行\(1\)操作。这是因为我们不管我们在\(1\)操作前做什么操作都会被其推平覆盖,是无用操......
  • P8047题解
    P8047[COCI2015-2016#4]GALAKSIJA题目传送门题解显然是要删边变加边的,然后联通性也是显然要用并查集维护的,就是路径异或和需要一个数据结构来维护。发现:加边删边不影响两个点的路径异或和。所以我们可以处理出每个点到\(1\)号节点的路径异或和\(d\),于是\(Path_{u,v}=d_u......
  • P8034题解
    P8034[COCI2015-2016#7]Ozljeda题目传送门题解评橙差不多了。手玩一下样例,很容易发现\(x\)的循环节为\(K+1\),每一段分别为\(a_1,a_2,a_3,\dots,a_K,\bigoplus_{i=1}^Ka_i\)这几项,然后恰好循环节的异或值为\(0\),所以就可以直接维护前缀异或值,然后取模求答案。代码:#i......
  • [AGC048D] Pocky Game 题解
    题目链接点击打开链接题目解法好难的题,想不出来一点!!!首先给出一个第一个结论:最优策略下,每个人每次只会取一个石子或者取完一堆石子题解区都没有严谨证明,\(at\)的\(editorial\)也没证,所以我只能感性理解:下面以先手为例。如果最左边的石子数\(>\)其余所有堆的石子数,那么先......
  • 题解 WD与数列
    P5161WD与数列可以想到原条件是一个差分形式,所以我们对原数组差分。然后发现答案其实就是\(\sum_{i<j}\min(lcp(i+1,j+1)+1,j-i)\)。这个东西先跑SA,然后建笛卡尔树。考虑对于一个区间,其值为\(x\)。那么相当于是求\(\sum_{l\inS,r\inT}\min(|sa_{l}-sa_{r}|,x)\)。笛......
  • AT_arc115_b [ARC115B] Plus Matrix 题解
    AT_arc115_b[ARC115B]PlusMatrix题解题意给定矩阵\(C_{n\timesn}\),求两个数列\(A_n,B_n\),使得\(C_{i,j}=A_i+B_j\)。分析画出一个表格来:213243502131324可以看出来,对于任意一列\(j\),\(C_{*,j}\)都存在有\(B_j\)的贡献。那么我们......
  • ELK之Filebeat自动断开问题解决
     自动断开命令 解决自动断开命令nohup./filebeat-e-cfilebeat.yml>./filebeat.log 2>&1& disown 其他的方式(目前我没有使用) 在linux操作系统/etc/systemd/system目录下创建一个filebeat.service文件,写入如下内容需要注意替换文件的位置以及版本[Unit]D......