UOJ#454. 【UER #8】打雪仗

UOJ#454. 【UER #8】打雪仗

http://uoj.ac/problem/454

分析:

  • 好玩的通信题~
  • 把序列分成三块,(bob)先发出这三块中询问点最多的一块给(alice)
  • 对于这一块,显然点数大于等于(frac{n}{3}),全部由(alice)输出。
  • 对于剩下的两块,先由(bob)告诉是否应该输出,(alice)再决定是否输出。
  • 这样,(alice)的次数是(667+frac{2n}{3})(bob)的次数是(2+frac{4n}{3}),均小于(1350),可以通过此题。

代码:

#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
char w[2050];
void pr(char s) {
	putchar(s);
	fflush(stdout);
}
int L[4],R[4];
int main() {
	FILE *fp=fopen("alice.in","r");
	int n,m;
	fscanf(fp,"%d%d%s",&n,&m,w+1);
	fclose(fp);
	int i;
	int block=667;
	L[1]=1; R[1]=block; L[2]=block+1; R[2]=block*2; L[3]=R[2]+1; R[3]=2*n; 

	int x=getchar()-'0',y=getchar()-'0';
	x=x*2+y;

	for(i=L[x];i<=R[x];i++) pr(w[i]);

	for(i=1;i<L[x];i++) {
		y=getchar();
		if(y=='1') pr(w[i]);
	}
	for(i=R[x]+1;i<=2*n;i++) {
		y=getchar();
		if(y=='1') pr(w[i]);
	}
}
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cstdlib>
using namespace std;
char w[2050];
void pr(char s) {
	putchar(s);
	fflush(stdout);
}
void print(int x) {
	pr(x/2+'0'); pr((x&1)+'0');
}
int n,m,p[2050],is[2050],L[4],R[4];
int main() {
	FILE *fp=fopen("bob.in","r");
	int n,m,i;
	fscanf(fp,"%d%d",&n,&m);
	for(i=1;i<=n;i++) fscanf(fp,"%d",&p[i]),is[p[i]]=1;
	fclose(fp);

	int block=667,c1=0,c2=0,c3=0;
	for(i=1;i<=block;i++) c1+=is[i];
	for(i=block+1;i<=2*block;i++) c2+=is[i];
	for(i=block*2+1;i<=2*n;i++) c3+=is[i];
	L[1]=1; R[1]=block; L[2]=block+1; R[2]=block*2; L[3]=R[2]+1; R[3]=2*n; 

	int x=0;
	if(c1>=333) x=1;
	if(c2>=333) x=2;
	if(c3>=333) x=3;

	print(x);

	for(i=L[x];i<=R[x];i++) w[i]=getchar();

	for(i=1;i<L[x];i++) {
		pr(is[i]+'0');
		if(is[i]) w[i]=getchar();
	}
	for(i=R[x]+1;i<=2*n;i++) {
		pr(is[i]+'0');
		if(is[i]) w[i]=getchar();
	}

	fp=fopen("bob.out","w");
	for(i=1;i<=n;i++) fprintf(fp,"%c",w[p[i]]);
}
原文地址:https://www.cnblogs.com/suika/p/10205947.html