社区讨论

gtoi C题

学术版参与者 5已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@mkia2p7i
此快照首次捕获于
2026/01/17 20:22
上个月
此快照最后确认于
2026/01/20 15:40
4 周前
查看原帖
CPP
#include<bits/stdc++.h>
#define il inline
#define ui unsigned int
#define ll long long
#define ull unsigned ll
#define lll __int128
#define db double
#define ldb long double
#define pii pair<int,int>
#define vi vector<int>
#define vpii vector<pii>
#define fir first
#define sec second
#define gc getchar
#define pc putchar
#define pb push_back
#define lb lower_bound
#define ub upper_bound
#define pct __builtin_popcount
#define mst(a,x) memset(a,x,sizeof a)
#define mcp(a,b) memcpy(a,b,sizeof b)
using namespace std;
const int N=2e5+10,INF=0x3f3f3f3f,MOD=998244353;
const ll INFll=0x3f3f3f3f3f3f3f3f;
il int rd() {int x=0,f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il ll rdll() {ll x=0; int f=1; char ch=gc(); while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=gc();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc(); return x*f;}
il void wr(int x) {if(x==INT_MIN) return printf("-2147483648"),void(); if(x<0) return pc('-'),wr(-x); if(x<10) return pc(x+'0'),void(); wr(x/10),pc(x%10+'0');}
il void wrll(ll x) {if(x==LLONG_MIN) return printf("-9223372036854775808"),void(); if(x<0) return pc('-'),wrll(-x); if(x<10) return pc(x+'0'),void(); wrll(x/10),pc(x%10+'0');}
il void wr(int x,const char *s) {wr(x),printf("%s",s);}
il void wrll(ll x,const char *s) {wrll(x),printf("%s",s);}
il int vmod(int x) {return x>=MOD?x-MOD:x;}
il int vadd(int x,int y) {return vmod(x+y);}
il int vsub(int x,int y) {return vmod(x-y+MOD);}
il int vmul(int x,int y) {return 1ll*x*y%MOD;}
il int qpow(int x,int y) {int r=1; for(;y;y>>=1,x=vmul(x,x)) if(y&1) r=vmul(r,x); return r;}
il void cadd(int &x,int y) {x=vmod(x+y);}
il void csub(int &x,int y) {x=vmod(x-y+MOD);}
il void cmul(int &x,int y) {x=vmul(x,y);}
il void cmax(int &x,int y) {x<y&&(x=y);}
il void cmaxll(ll &x,ll y) {x<y&&(x=y);}
il void cmin(int &x,int y) {x>y&&(x=y);}
il void cminll(ll &x,ll y) {x>y&&(x=y);}
int n,a[N],aa[N];
vpii as;
void QwQ() {
	n=rd();
	for(int i=1;i<=n;i++) a[i]=rd();
//	for(int i=1;i<=n;i++) a[i]=i;
//	random_shuffle(a+1,a+1+n);
	if(n==2) return puts(a[1]==1?"0":"-1"),void();
	else if(n==3) return puts(a[1]==1&&a[2]==2?"0":a[1]==3&&a[2]==2?"1\n1 3":"-1"),void();
	else if(n>=5) {
		mcp(aa,a);
		for(int i=1;i<=n-2;i++) if((a[i]&1)!=(i&1)) {
			int p=0;
			for(int j=i+2;j<=n;j++) if((a[j]&1)==(i&1)) {p=j; break;}
			if(!p) {
				mcp(a,aa),as.clear();
				for(int i=1;i<=n;i++) if(a[i]!=i) {
					int p=0;
					for(int j=1;j<=n;j++) if(a[j]==i) {p=j; break;}
					if(p!=i+1) as.pb({i,p}),reverse(a+i,a+p+1);
					else if(p>=n-1) return wr(-1,"\n");
					else as.pb({p,p+2}),reverse(a+p,a+p+3),as.pb({i,p+2}),reverse(a+i,a+p+3);
				}
				wr(as.size(),"\n");
				for(auto [l,r]:as) wr(l," "),wr(r,"\n");
				return;
			}
			as.pb({i,p}),reverse(a+i,a+p+1);
		}
		if((a[n]&1)!=(n&1)) as.pb({n-4,n-1}),reverse(a+n-4,a+n),as.pb({n-3,n}),reverse(a+n-3,a+n+1);
	}
	for(int i=1;i<=n;i++) if(a[i]!=i) {
		int p=0;
		for(int j=1;j<=n;j++) if(a[j]==i) {p=j; break;}
		if(p!=i+1) as.pb({i,p}),reverse(a+i,a+p+1);
		else if(p>=n-1) return wr(-1,"\n");
		else as.pb({p,p+2}),reverse(a+p,a+p+3),as.pb({i,p+2}),reverse(a+i,a+p+3);
	}
	wr(as.size(),"\n");
	for(auto [l,r]:as) wr(l," "),wr(r,"\n");
}
signed main() {
//	freopen("in.in","r",stdin),freopen("out.out","w",stdout);
	int T=1; while(T--) QwQ();
}
思路:
考虑那个很奇怪的 aia_iii 同余的部分分。
会发现你乱写这么一个东西都能过:从左往右扫,找当前 ii 的位置 pp,翻转 [i,p][i,p],如果 p=i+1p=i+1 就完了。
考虑把序列变成这个样子,将 aia_i 为奇数的看作 11,偶数的看作 00,你要变成 10101010101010101010\dots 这样一个序列。还是考虑从左往右扫,在后面找一个和当前 ii 匹配的位置 pp 并翻转。
会发现如果这样末尾形如 0100101001 或者 1011010110 就完了,但此时可以依次翻转 [n4,n1][n-4,n-1][n3,n][n-3,n] 来变成 0101 相间。
特判一下 n=4n=4 的情况即可。
这个东西怎么证明次数是 1.5n1.5n 以内的?

回复

4 条回复,欢迎继续交流。

正在加载回复...