Codeforces 1058 Div 2 (A-E)

在 Print 之前

突然发现已经很久没写过博客了,前一晚才搭好这个博客样式,正好晚上熬夜打一下 Div 2。

赛时3941分,排在471位,T5双指针写挂了,调了一个小时没调出来。

A - MEX Partition

水题一道。

不难发现,答案就是 \(MEX(A)\)。

cpp 复制代码
#include <bits/stdc++.h>
#define pll pair<ll,ll>
#define pld pair<ld,ld>
typedef long long ll;
typedef long double ld;
typedef int praise_long_long;
namespace io {
	using namespace std;
	inline ll read() {
		char x=getchar();
		ll ans=0,f=1;
		while(x<'0'||x>'9') {
			if(x=='-') {
				f*=(-1);
			}
			x=getchar();
		}
		while(x>='0'&&x<='9') {
			ans*=10;
			ans+=(x-'0');
			x=getchar();
		}
		return ans*f;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			x=-x;
		}
		if(x>=10) {
			print(x/10);
			putchar(x%10+'0');
		}
		else {
			putchar(x+'0');
		}
	}
}
using namespace io;
const ll N=2e5+5,mod=1e9+7,inf=2e18;
const ld eps=1e-6;
ll n,a[N]; 
inline void solve() {
	n=read();
	ll cnt=0;
	for(ll i=1;i<=n;i++) {
		a[i]=read();
	}
	sort(a+1,a+1+n);
	for(ll i=1;i<=n;i++) {
		if(a[i]!=cnt) {
			break;
		}
		else {
			while(a[i]==a[i+1]) {
				i++;
			}
			cnt++;
		}
	}
	print(cnt);
	puts("");
}
praise_long_long main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ll T=1;
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}
/**/

B - Distinct Elements

其实不难发现,当 \(a_i\) 在之前没有出现过时,则有 \(b_i-b_{i-1}=i\),这样我们就可以给 \(a_i\) 安一个新的数。

反之若 \(b_i-b_{i-1} \not= i\),则 \(a_i\) 必定与 \(a_{i-(b_i-b_{i-1})}\) 相同。

cpp 复制代码
#include <bits/stdc++.h>
#define pll pair<ll,ll>
#define pld pair<ld,ld>
typedef long long ll;
typedef long double ld;
typedef int praise_long_long;
namespace io {
	using namespace std;
	inline ll read() {
		char x=getchar();
		ll ans=0,f=1;
		while(x<'0'||x>'9') {
			if(x=='-') {
				f*=(-1);
			}
			x=getchar();
		}
		while(x>='0'&&x<='9') {
			ans*=10;
			ans+=(x-'0');
			x=getchar();
		}
		return ans*f;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			x=-x;
		}
		if(x>=10) {
			print(x/10);
			putchar(x%10+'0');
		}
		else {
			putchar(x+'0');
		}
	}
}
using namespace io;
const ll N=2e5+5,mod=1e9+7,inf=2e18;
const ld eps=1e-6;
ll n,a[N],b[N];
set<ll> st;
inline void solve() {
	n=read();
	st.clear();
	for(ll i=1;i<=n;i++) {
		b[i]=read();
		st.insert(i);
	}
	for(ll i=1;i<=n;i++) {
		if(b[i]==b[i-1]) {
			a[i]=a[i-1];
		}
		else {
			a[i]=b[i]-b[i-1];
		}
		ll lt=i-a[i];
		if(!lt) {
			a[i]=(*st.begin());
			st.erase(st.begin());
		}
		else {
			a[i]=a[lt];
		}
	}
	for(ll i=1;i<=n;i++) {
		cout<<a[i]<<' ';
	}
	puts("");
}
praise_long_long main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ll T=1;
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}
/**/

C - Reverse XOR

拿 \(6\) 举例子,它的二进制是 \(110_2\),我们发现只需在开头加上一个 \(0\) 或在结尾减去一个 \(0\) 即可。

所以可以删去末尾的 \(0\) 来完成或者在开头添加 \(0\) 即可。

注意奇数的回文串中间一位应为 \(0\)。

cpp 复制代码
#include <bits/stdc++.h>
#define pll pair<ll,ll>
#define pld pair<ld,ld>
typedef long long ll;
typedef long double ld;
typedef int praise_long_long;
namespace io {
	using namespace std;
	inline ll read() {
		char x=getchar();
		ll ans=0,f=1;
		while(x<'0'||x>'9') {
			if(x=='-') {
				f*=(-1);
			}
			x=getchar();
		}
		while(x>='0'&&x<='9') {
			ans*=10;
			ans+=(x-'0');
			x=getchar();
		}
		return ans*f;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			x=-x;
		}
		if(x>=10) {
			print(x/10);
			putchar(x%10+'0');
		}
		else {
			putchar(x+'0');
		}
	}
}
using namespace io;
const ll N=2e5+5,mod=1e9+7,inf=2e18;
const ld eps=1e-6;
ll n,cnt;
string num,sum;
inline void solve() {
	n=read();
	cnt=0;
	sum="";
	num="";
	while(n) {
		num+=(char)(n%2+'0');
		n/=2;
		cnt++;
	}
	reverse(num.begin(),num.end());
	for(ll i=cnt;i<=cnt*2;i++) {
		string t=sum+num;
		string kl=t;
		reverse(kl.begin(),kl.end());
		if(t==kl) {
			if(i&1) {
				if(t[i/2]=='0') {
					puts("YES");
					return ;
				}
			}
			else {
				puts("YES");
				return ;
			}
		}
		sum+='0';
	}
	puts("NO");
}
praise_long_long main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ll T=1;
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}
/**/

D - MAD Interactive Problem

不难想出可以用 \(2*n\) 次访问出第二个 \(i\) 的位置,然后再用 \(n\) 次查询来锁定第一个位置。

cpp 复制代码
#include <bits/stdc++.h>
#define pll pair<ll,ll>
#define pld pair<ld,ld>
typedef long long ll;
typedef long double ld;
typedef int praise_long_long;
namespace io {
	using namespace std;
	inline ll read() {
		char x=getchar();
		ll ans=0,f=1;
		while(x<'0'||x>'9') {
			if(x=='-') {
				f*=(-1);
			}
			x=getchar();
		}
		while(x>='0'&&x<='9') {
			ans*=10;
			ans+=(x-'0');
			x=getchar();
		}
		return ans*f;
	}
	inline void print(ll x) {
		if(x<0) {
			putchar('-');
			x=-x;
		}
		if(x>=10) {
			print(x/10);
			putchar(x%10+'0');
		}
		else {
			putchar(x+'0');
		}
	}
}
using namespace io;
const ll N=6e2+5,mod=1e9+7,inf=2e18;
const ld eps=1e-6;
ll n,a[N],num[N],cnt,vis[N];
inline void input() {
	cout<<"? "<<cnt;
	cout.flush();
	for(ll i=1;i<=cnt;i++) {
		cout<<' '<<num[i];
		cout.flush();
	}
	puts("");
	cout.flush();
}
inline void input1() {
	for(ll i=1;i<=cnt;i++) {
		num[i]=vis[i];
	}
	input();
}
inline void solve() {
	n=read();
	cnt=0;
	num[++cnt]=1;
	a[1]=0;
	for(ll i=2;i<=2*n;i++) {
		a[i]=0;
		num[++cnt]=i;
		input();
		ll sum=read();
		if(sum) {
			a[i]=sum;
			vis[sum]=i;
			cnt--;
		}
	}
	cnt=n;
	for(ll i=1;i<=2*n;i++) {
		if(a[i]) {
			continue;
		}
		vis[++cnt]=i;
		input1();
		ll sum=read();
		a[i]=sum;
		cnt--;
	}
	cout<<'!';
	cout.flush();
	for(ll i=1;i<=2*n;i++) {
		cout<<' '<<a[i];
		cout.flush();
	}
	puts("");
	cout.flush();
}
praise_long_long main() {
//	freopen(".in","r",stdin);
//	freopen(".out","w",stdout);
	ll T=1;
	T=read();
	while(T--) {
		solve();
	}
	return 0;
}
/**/

晚上来写E/F,再修改一下前面的题解