[JOIST 2025 Day3] 多方通信 题解
思路提供自 @0x824EE 大佬。
很智慧的题。
考虑
不妨让每个结点在经过某些预处理后的所有轮次中,在自己的黑板上写的字母固定。尝试预处理这样的信息:一个结点在之后的轮次中黑板上的字母为
接着在树上二分,假设当前确定的区间为
但是限定的次数为
考虑“父亲读取儿子信息”的本质,其实就相当于对于一个区间
尝试把思路拓展到
下面给出
生成答案代码:
#include<bits/stdc++.h>
using namespace std;
inline int lowbit(int x){
return x&-x;
}
int main(){
freopen("output_03.txt","w",stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int n=48,l=9; cout<<l<<endl;
for(int i=1;i<=n;i++){
cout<<i<<endl;
vector C(n+1,vector<char>(l,'F'));
vector P(n+1,vector<int>(l));
function<void(int,int,int)> dfs=[&](int l,int r,int d){
if(l==r)return;
int m=l+r>>1;
dfs(l,m,d-1),dfs(m+1,r,d-1);
for(int j=l;j<=m;j++)
P[j][d]=r;
for(int j=m+1;j<=r;j++)
P[j][d]=m;
for(int j=l;j<=r;j++)
if(C[j][d]=='F')C[j][d]=d?C[j][d-1]:(j==i?'T':'F');
if(C[m][d]=='T')C[r][d+1]='T';
}; // 递归预处理信息
dfs(1,n/3,3),dfs(n/3+1,n/3*2,3),dfs(n/3*2+1,n,3);
for(int i=1;i<=n/3;i++)
if(P[i][4]=n;C[i][4]=='F')C[i][4]=C[i][3];
for(int i=n/3+1;i<=n;i++)
if(P[i][4]=n/3;C[i][4]=='F')C[i][4]=C[i][3];
int x,y;
if(i<=n/3)x=1,y=n/3;
else if(i<=n/3*2)x=n/3+1,y=n/3*2;
else x=n/3*2+1,y=n;
for(int j=5;j<l;j++){
for(int p=1;p<=n;p++)
C[p][j]=C[p][j-1];
int m=x+y>>1;
for(int p=1;p<=n;p++)
P[p][j]=m;
if(i<=m)y=m;
else x=m+1;
} // 二分过程
for(int j=1;j<=n;j++,cout<<endl)
for(int k=0;k<l;k++)
cout<<C[j][k]<<' '<<P[j][k]<<' ';
}
return 0;
}
Special Judge:
#include<bits/stdc++.h>
using namespace std;
int main(){
freopen("output_03.txt","r",stdin);
int n=48,l; cin>>l;
vector c(n,vector(n,vector<char>(l)));
vector p(n,vector(n,vector<int>(l)));
for(int i=0;i<n;i++){
int x; cin>>x;
for(int j=0;j<n;j++)
for(int k=0;k<l;k++)
cin>>c[i][j][k]>>p[i][j][k],p[i][j][k]--;
}
bool f1=true,f2=true;
for(int x=0;x<n;x++)
for(int y=0;y<n;y++)
if(x!=y){
for(int a=0;a<n;a++){
string s=(a==x?"T":"F"),t=(a==y?"T":"F");
for(int i=0;i<l;i++){
if(s==t)f1&=c[x][a][i]==c[y][a][i]&&p[x][a][i]==p[y][a][i];
s+=c[x][p[x][a][i]][i],t+=c[y][p[y][a][i]][i];
}
f2&=s!=t;
}
}
cout<<"Condition 1: "<<(f1?"Yes\n":"No\n");
cout<<"Condition 2: "<<(f2?"Yes\n":"No\n");
cout<<(f1&&f2?"Accepted\n":"Wrong Answer\n");
return 0;
}