CF772E Verifying Kingdom

Posted miracevin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF772E Verifying Kingdom相关的知识,希望对你有一定的参考价值。

CF772E Verifying Kingdom 

有趣的交互题(交互题都挺有意思的)

%ywy

增量法构造

考虑加入了前i个叶子

那么树是前i个叶子构成的虚树!

最后n个叶子构成的虚树就是答案!

怎样确定第i+1个叶子的位置?

用点分治“二分”!

每次找到当前连通块的重心rt,注意rt不能是叶子

维护rt的两个儿子,父亲,两个儿子内部随意一个叶子has[0],has[1]

用has[0],has[1],i+1进行ask,X,Y,Z唯一确定一个方向:fa、rson,lson

递归进去二分。

边界:

1.往fa走没有fa,新建

2.往fa、son已经vis了,这个边上长出一个点和一个叶子来

3.当前点是叶子,新建节点,叶子和i+1连在下面。

询问次数O(nlogn)

复杂度O(n^2)(每次现找重心,只递归一边。) 

 

注意:

1.点分治找到rt之后再dfs才是真正size。。

2.rt和进入点x不能弄混了。。

 

Code

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^‘0‘)
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x)
    char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch==-)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);
template<class T>il void output(T x)if(x/10)output(x/10);putchar(x%10+0);
template<class T>il void ot(T x)if(x<0) putchar(-),x=-x;output(x);putchar( );
template<class T>il void prt(T a[],int st,int nd)for(reg i=st;i<=nd;++i) ot(a[i]);putchar(\n);
namespace Modulo
const int mod=998244353;
int ad(int x,int y)return (x+y)>=mod?x+y-mod:x+y;
void inc(int &x,int y)x=ad(x,y);
int mul(int x,int y)return (ll)x*y%mod;
void inc2(int &x,int y)x=mul(x,y);
int qm(int x,int y=mod-2)int ret=1;while(y)if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;return ret;

//using namespace Modulo;
namespace Miracle
const int N=2005;
int n;
char s[233];
int fa[N],ch[N][2],has[N][2];//has a leaf
int tot;
int ask(int a,int b,int c)
    printf("%d %d %d\n",a,b,c);
    fflush(stdout);
    scanf("%s",s+1);
    return (s[1]-X);

bool vis[N];
int rt,sz[N];
int nowsz;
void dfs(int x,int od)
    if(!x) return;
    // cout<<" x "<<x<<" od "<<od<<" "<<fa[x]<<" "<<ch[x][0]<<" "<<ch[x][1]<<" visf "<<vis[fa[x]]<<" "<<(fa[x]!=od)<<endl;
    sz[x]=1;
    int mx=0,now;
    if(!vis[fa[x]]&&fa[x]!=od) dfs(fa[x],x),mx=max(mx,sz[fa[x]]),sz[x]+=sz[fa[x]];
    if(!vis[ch[x][0]]&&ch[x][0]!=od) dfs(ch[x][0],x),mx=max(mx,sz[ch[x][0]]),sz[x]+=sz[ch[x][0]];
    if(!vis[ch[x][1]]&&ch[x][1]!=od) dfs(ch[x][1],x),mx=max(mx,sz[ch[x][1]]),sz[x]+=sz[ch[x][1]];
    

    if((ch[x][0]||ch[x][1])&&(max(mx,nowsz-sz[x])<=nowsz/2)) rt=x;

void dfs2(int x,int od)
    if(!x) return;
    // cout<<" x "<<x<<" od "<<od<<" "<<fa[x]<<" "<<ch[x][0]<<" "<<ch[x][1]<<" visf "<<vis[fa[x]]<<" "<<(fa[x]!=od)<<endl;
    sz[x]=1;
    if(!vis[fa[x]]&&fa[x]!=od) dfs2(fa[x],x),sz[x]+=sz[fa[x]];
    if(!vis[ch[x][0]]&&ch[x][0]!=od) dfs2(ch[x][0],x),sz[x]+=sz[ch[x][0]];
    if(!vis[ch[x][1]]&&ch[x][1]!=od) dfs2(ch[x][1],x),sz[x]+=sz[ch[x][1]];

void fin(int x,int id)
    // cout<<" fin "<<x<<" nowsz "<<nowsz<<endl;
    if(!ch[x][0]&&!ch[x][1])//leaf
        // cout<<" leaf "<<endl;
        ++tot;
        int d=ch[fa[x]][1]==x;
        ch[tot][0]=x;ch[tot][1]=id;fa[tot]=fa[x];ch[fa[x]][d]=tot;
        fa[x]=tot;fa[id]=tot;
        has[tot][0]=x;has[tot][1]=id;
        return ;
    
    rt=0;
    dfs(x,0);
    x=rt;
    dfs2(rt,0);
    // cout<<" rt "<<rt<<" has "<<has[rt][0]<<" "<<has[rt][1]<<endl;
    int bc=ask(has[rt][0],has[rt][1],id);
    vis[rt]=1;
    if(bc==0)
        if(fa[x])
            if(vis[fa[x]])
                int y=fa[x];
                int d=ch[y][1]==x;
                ch[y][d]=++tot;
                fa[tot]=y;
                ch[tot][d]=x;fa[x]=tot;
                ch[tot][d^1]=id;
                fa[id]=tot;
                has[tot][d]=has[x][0];
                has[tot][d^1]=id;
            else
                nowsz=sz[fa[x]];
                fin(fa[x],id);
            
        else
            // cout<<" nofa "<<endl;
            fa[x]=++tot;
            ch[tot][0]=x;
            ch[tot][1]=id;
            has[tot][0]=has[x][0];
            has[tot][1]=id;
            fa[id]=tot;
        
    else 
        int p;
        if(bc==1) p=1;
        else p=0;
        if(ch[x][p])
            int z=ch[x][p];
            // cout<<" z "<<z<<endl;
            if(vis[z])
                ++tot;
                ch[x][p]=tot;fa[tot]=x;
                ch[tot][p]=z;fa[z]=tot;
                ch[tot][p^1]=id;fa[id]=tot;
                has[tot][p^1]=id;
                has[tot][p]=has[z][0];
            else
                nowsz=sz[z];
                fin(z,id);
            
        else 
            assert(-1>0);
        
    

int main()
    rd(n);
    tot=n;
    ++tot;
    has[tot][0]=ch[tot][0]=1;fa[1]=tot;
    has[tot][1]=ch[tot][1]=2;fa[2]=tot;
    for(reg i=3;i<=n;++i)
        // cout<<"ii ----------------------- "<<i<<endl;
        memset(vis,0,sizeof vis);
        memset(sz,0,sizeof sz);
        // for(reg j=1;j<i;++j) vis[j]=1;
        nowsz=2*(i-1)-1;
        // cout<<" vis[55] "<<vis[55]<<endl;
        fin(tot,i);
        // for(reg i=1;i<=tot;++i)
        //     cout<<i<<" : fa "<<fa[i]<<" ls "<<ch[i][0]<<" rs "<<ch[i][1]<<" hasls "<<has[i][0]<<" hasrs "<<has[i][1]<<endl;
        // 
    
    // prt(fa,1,tot);
    printf("-1\n");
    for(reg i=1;i<=tot;++i)
        if(!fa[i]) fa[i]=-1;
        ot(fa[i]);
    
    return 0;



signed main()
    Miracle::main();
    return 0;


/*
   Author: *Miracle*
*/

交互题都是要找到一个方向去构造的

比如这个就是增量构造

10*n,类似nlogn,二分?

考虑定位,发现点分治最合适了。

 

以上是关于CF772E Verifying Kingdom的主要内容,如果未能解决你的问题,请参考以下文章

CF1312F Attack on Red Kingdom

[CF115E]Linear Kingdom Races

CF613D Kingdom and its Cities

CF1336 Linova and Kingdom

CF687DDividing Kingdom II 线段树+并查集

CF613D Kingdom and its Cities