您的位置:首页 > 其它

[交互 点分治] Codeforces 772E VK Cup 2017 - Round 2 E. Verifying Kingdom

2017-06-13 22:34 405 查看
本来的想法是能够找出叶子的兄弟 那么就把他们以及他们的父亲缩起来

但是很难找兄弟

看了题解发现是从初始一个点加点 相当于把缩的拆回去

通过点分治 我们找出当前树的重心 这里的重心是以叶子数量为权的

然后ask一下(g的左子树中的叶子,g的右子树中的叶子,当前要加的点)

有一些细节要处理

那么就可以确定当前点是在左子树 右子树还是子树外

询问复杂度O(nlogn) 时间复杂度O(n2)

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cassert>
using namespace std;

inline int ask(int a1,int a2,int a3){ // 1: a1,a2 2: a2,a3 3: a1,a3;
printf("%d %d %d\n",a1,a2,a3);
fflush(stdout); char c;
do c=getchar(); while (!(c>='A' && c<='Z'));
return c=='X'?1:(c=='Y'?2:3);
}

const int N=2005;

int n;
int ncnt,pnt;
int ls
,rs
,ps
,lc
,rc
;
int size
,depth
,sum,minv,rt;
int del
;

inline void dfs(int u,int fa){
size[u]=u<=n; depth[u]=depth[fa]+1; int maxv=0;
int v;
v=ls[u];
if (v && v!=fa && !del[v]){
dfs(v,u); size[u]+=size[v];
maxv=max(maxv,size[v]);
}
v=rs[u];
if (v && v!=fa && !del[v]){
dfs(v,u); size[u]+=size[v];
maxv=max(maxv,size[v]);
}
v=ps[u];
if (v && v!=fa && !del[v]){
dfs(v,u); size[u]+=size[v];
maxv=max(maxv,size[v]);
}
maxv=max(maxv,sum-size[u]);
if (u>n && maxv<minv) minv=maxv,rt=u;
}

inline void _new(int u){
int a=++ncnt,b=++pnt;
if (ps[u]) { if (ls[ps[u]]==u) ls[ps[u]]=a; else rs[ps[u]]=a; }
ps[a]=ps[u]; rs[a]=u; ls[a]=b;
ps[u]=a; ps[b]=a;
lc[b]=rc[b]=b; lc[a]=lc[ls[a]]; rc[a]=rc[rs[a]];
}

int S=0,Si;
inline void Size(int u,int fa){
S++; Si+=u<=n; int v;
v=ls[u]; if (v && v!=fa && !del[v]) Size(v,u);
v=rs[u]; if (v && v!=fa && !del[v]) Size(v,u);
v=ps[u]; if (v && v!=fa && !del[v]) Size(v,u);
}

int vst
;

inline void Divide(int u){
S=0; Si=0; Size(u,0);
//assert(u); vst[u]=1;
if (S==1) { _new(u); return; }
sum=Si; minv=1<<30;
dfs(u,0);
int g=rt; while ((!ls[g] || del[ls[g]]) && (!rs[g] || del[rs[g]])) g=ps[g];
int t=ask(lc[ls[g]],rc[rs[g]],pnt+1);
if (t==1){ //ls[u],rs[u]
del[ls[g]]=del[rs[g]]=1;
Divide(g);
}else if (t==2){ //rs[u],g
del[g]=1;
Divide(rs[g]);
}else{
del[g]=1;
Divide(ls[g]);
}
}

int main(){
//freopen("t.in","r",stdin);
//freopen("t.out","w",stdout);
scanf("%d",&n);
ncnt=n; pnt=1; lc[1]=rc[1]=1;
for (int i=2;i<=n;i++){
for (int j=1;j<=2*n-1;j++) del[j]=vst[j]=0;
Divide(1);
}
printf("-1\n");
for (int i=1;i<=ncnt;i++)
printf("%d ",ps[i]?ps[i]:-1);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐