[交互 点分治] Codeforces 772E VK Cup 2017 - Round 2 E. Verifying Kingdom
2017-06-13 22:34
405 查看
本来的想法是能够找出叶子的兄弟 那么就把他们以及他们的父亲缩起来
但是很难找兄弟
看了题解发现是从初始一个点加点 相当于把缩的拆回去
通过点分治 我们找出当前树的重心 这里的重心是以叶子数量为权的
然后ask一下(g的左子树中的叶子,g的右子树中的叶子,当前要加的点)
有一些细节要处理
那么就可以确定当前点是在左子树 右子树还是子树外
询问复杂度O(nlogn) 时间复杂度O(n2)
但是很难找兄弟
看了题解发现是从初始一个点加点 相当于把缩的拆回去
通过点分治 我们找出当前树的重心 这里的重心是以叶子数量为权的
然后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; }
相关文章推荐
- Technocup 2017 - Elimination Round 1 (Rated for Div. 2) C. Guess the Array 交互题+解n元方程组
- Technocup 2017 - Elimination Round 1 C. Guess the Array (交互题)
- Technocup 2017 - Elimination Round 1 C 交互
- [线段树 杂题] Codeforces 806E VK Cup 2017 Round 3 E. Blog Post Rating
- Codeforces Round #389 (Div. 2, Rated, Based on Technocup 2017 - Elimination Round 3) A
- 【树形dp】Codeforces Round #405 (rated, Div. 1, based on VK Cup 2017 Round 1) B. Bear and Tree Jumps
- Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)&&Codeforces 861A k-rounding【暴力】
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) A Is it rated?
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) B. T-Shirt Hunt(模拟)
- Technocup 2017 - Elimination Round 1 (Unofficially Open for Everyone, Rated for Div. 2) C
- Codeforces VK Cup 2017 - Round 2
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)A. Vicious Keyboard
- Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2) ABCD
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) C
- Codeforces Round #403 (Div. 2, based on Technocup 2017 Finals) A. Andryusha and Socks
- 【解题报告】Codeforces Round #409 (rated, Div. 2, based on VK Cup 2017 Round 2)
- Codeforces Round #434 (Div. 2, based on Technocup 2018 Elimination Round 1)&&Codeforces 861B Which floor?【枚举,暴力】
- Codeforces Round #412 (rated, Div. 2, base on VK Cup 2017 Round 3) C. Success Rate(数学,二分)
- Codeforces Round #380 (Div. 1, Rated, Based on Technocup 2017 - Elimination Round 2)
- Technocup 2017 - Elimination Round 1 (Unofficially Open for Everyone, Rated for Div. 2) D