[題解](更新中)MX-X6 A~B

Sinktank發表於2024-10-04

Portal:https://www.luogu.com.cn/contest/200833

\(\bf{100+100+12+0+7+0=\color{indianred}219\color{black}\ ,\ rk230}\)

A - もしも

容易發現可以構造\(1,x\)\(x,1\)讓序列如\(\dots,1,x,1,x,1,x,\dots\)這樣迴圈。只需要關注\(n\)的奇偶性即可。

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
using namespace std;
int t,n,an;
signed main(){
	cin>>t;
	while(t--){
		cin>>n>>an;
		if(n&1) cout<<an<<" "<<1<<"\n";
		else cout<<1<<" "<<an<<"\n";
	}
	return 0;
}

B - さよならワンダーランド

根據題意,我們找到的\(j\)需要滿足:

  • \(j\ge 1-i\)
  • \(j\le n-i\)
  • \(j\ge a_i\)
  • \(j\le a_{i+j}\)

其中前\(3\)項都是靜態的,與\(j\)無關的,所以我們在前\(3\)項限制的範圍\([l,r]\)內尋找\(j\)使得\(j\le a_{i+j}\)即可,這也是此題的關鍵點。

我們記\(b_i=a_i-i\),那麼
\(a_{i+j}\ge j\)
\(\iff [\max\limits_{j\in [l,r]}a_{i+j}-j]\ge 0\)
\(\iff [\max\limits_{j\in [l,r]}a_{i+j}-(i+j)]\ge (-i)\)
\(\iff \max\limits_{j\in [l,r]}b_{i+j} \ge (-i)\)

因此我們僅需用ST表維護出\(b\)的區間最大值,然後查詢是否存在就直接看最後那個式子是否成立;查詢具體位置我直接用的二分,如果\([l,mid]\)成立,那麼左邊一定存在合法的\(j\)(不是說右邊沒有),否則\(j\)一定在右邊。

點選檢視程式碼
#include<bits/stdc++.h>
#define int long long
#define N 300010
using namespace std;
int n,a[N],f[N][30],lg[N];
void init(){
	lg[0]=-1;
	for(int i=1;i<=n;i++) lg[i]=lg[i/2]+1;
	for(int i=1;i<=lg[n];i++){
		for(int j=1;j+(1<<i)-1<=n;j++){
			f[j][i]=max(f[j][i-1],f[j+(1<<(i-1))][i-1]);
		}
	}
}
int query(int l,int r){
	if(r<l) return LLONG_MIN;
	int len=lg[r-l+1];
	return max(f[l][len],f[r-(1<<len)+1][len]);
}
int modi(int a){
	return min(max(1ll,a),n);
}
signed main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		f[i][0]=a[i]-i;
	}
	init();
	for(int i=1;i<=n;i++){
		int l=max(a[i],1-i),r=n-i;
		if(query(i+l,i+r)>=-i){
			while(l<r){
				int mid=(l+r)>>1;
				if(query(i+l,i+mid)>=-i) r=mid;
				else l=mid+1;
			}
			cout<<"1 "<<l<<"\n";
		}else cout<<"0\n";
	}
	return 0;
}

相關文章