首页 > 其他 > 详细

[WC2018] 即时战略

时间:2020-01-12 16:15:19      阅读:71      评论:0      收藏:0      [点我收藏+]

题目

终于会写交互了

粗略观察一下,发现这道题树的部分查询次数要求是\(O(n\log n)\)级别,链部分要求是\(O(n)\)级别而且要求这个常数比较小

先来考虑链怎么搞,我们可以随机一个序列,之后按照顺序explore这些点,如果一个点已经被探明了,我们就跳过它;我们维护当前已经扩展出来的这条链的左右端点,每次遇到一个未探明点时,就用这左右两个端点分别explore一下,看看这个点在哪个端点的下面,之后一直搞下去,直到这个点被探明为止,之后再将这个点设为新的端点。

不难发现这样每个点最多会被explore两次,这询问次数好像有点超的样子;但是我们随机了序列,这相当于对链的两边做随机分治,于是询问次数是期望\(n+\log n\)的。

再来考虑树的情况,一个直观的想法是分治,设当前的根为\(x\),我们把\(x\)子树内部的点跟\(x\)explore一遍,之后按照得到的结果把他们分到不同的子树中去;这样的询问次数是\(\sum_{i=1}^ndep_i\),又能过完全二叉树的subtask了。

这个询问次数太垃圾了,我们需要做的是将每个点的询问次数优化到\(\log n\)

假如我们现在有一棵点分树,如果我们要探明一个点\(x\),我们就explore一下当前分治重心与\(x\);我们把得到的结果一路暴跳,这样就能知道下一层的分治重心是谁,之后继续到下一层的分治重心去询问,直到\(x\)被探明,之后再把\(x\)加入点分树。

这样探明\(x\)的询问次数是点分树的树高次,时间复杂度是点分树树高的平方次,于是只要我们能保证点分树\(\log\)的树高,就能解决这个问题了。于是是我们只需要一个替罪羊重构就好了。

这样询问次数是\(O(n\log n)\)的,时间复杂度是\(O(n\log^2 n)\)

代码

#include<bits/stdc++.h>
#include "rts.h"
#define re register
#define max(a,b) ((a)>(b)?(a):(b))
const int maxn=3e5+5;
int c[maxn],p[maxn];
std::vector<int> d[maxn];
void dfs(int x,int fa,int n) {
    for(re int i=2;i<=n;i++) {
        if(c[i]) continue;
        int v=explore(x,i);
        if(c[v]) continue;
        c[v]=1;dfs(v,x,n);
    }
}
void divide(int x) {
    int rt[2];rt[0]=rt[1]=0;
    for(re int i=0;i<d[x].size();++i) {
        if(x==d[x][i]) continue;
        int t=explore(x,d[x][i]);
        d[t].push_back(d[x][i]);
        if(rt[0]==t||rt[1]==t) continue;
        if(!rt[0]) rt[0]=t;
        else if(!rt[1]) rt[1]=t;
    }
    if(rt[0]) divide(rt[0]);
    if(rt[1]) divide(rt[1]);
}
const double alpha=0.75;
struct E{int v,nxt;}e[maxn<<1];
int head[maxn],Mnow,sum[maxn],vis[maxn],nrt,S,rt,mx[maxn],fa[maxn],num,tim,del[maxn];
inline void add(int x,int y) {
    e[++num].v=y;e[num].nxt=head[x];head[x]=num;
}
void getrt(int x,int Fa) {
    sum[x]=1;mx[x]=0;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]==tim||e[i].v==Fa)continue;
        getrt(e[i].v,x);sum[x]+=sum[e[i].v];
        mx[x]=max(sum[e[i].v],mx[x]);
    }
    mx[x]=max(mx[x],S-sum[x]);
    if(mx[x]<Mnow) Mnow=mx[x],nrt=x;
}
void clr(int x,int Fa) {
    del[x]=0;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(e[i].v==Fa||vis[e[i].v]==tim) continue;
        clr(e[i].v,x);
    }
}
void Dfs(int x) {
    vis[x]=tim;
    for(re int i=head[x];i;i=e[i].nxt) {
        if(vis[e[i].v]==tim) continue;
        Mnow=maxn,S=sum[e[i].v];getrt(e[i].v,0);
        fa[nrt]=x;sum[nrt]=sum[e[i].v];Dfs(nrt);
    }
}
inline void rebuild(int x) {
    ++tim;for(re int i=fa[x];i;i=fa[i]) vis[i]=tim;
    clr(x,0);Mnow=maxn,S=sum[x],getrt(x,0);
    if(rt==x) rt=nrt;
    fa[nrt]=fa[x];sum[nrt]=sum[x];Dfs(nrt);
}
inline void pushup(int x) {
    if(!fa[x]) {
        if(del[x]) rebuild(x);
        return;
    }
    ++sum[fa[x]];if(sum[fa[x]]*alpha<sum[x]) del[fa[x]]=1;
    pushup(fa[x]);if(del[x]) rebuild(x);
}
inline void ins(int x) {
    int u=rt;
    while(!c[x]) {
        int v=explore(u,x);
        if(c[v]) {
            while(fa[v]!=u) v=fa[v];
            u=v;continue;
        }
        add(u,v),add(v,u);fa[v]=u;
        sum[v]=1;pushup(v);
        u=v;c[v]=1;
    }
}
void play(int n, int T, int dataType) {
    if(n<=100&&dataType==1) {
        dfs(1,0,n);return;
    }
    if(dataType==3) {
        for(re int i=1;i<n;++i)p[i]=i+1;
        srand(time(0));
        std::random_shuffle(p+1,p+n);
        int rt[2];rt[0]=1,rt[1]=1;
        int t=p[2],u;
        while(rt[1]!=t) {
            u=explore(rt[1],t);
            c[u]=1;rt[1]=u;
        }
        for(re int i=3;i<n;i++) {
            int x=p[i];if(c[x]) continue;
            u=explore(rt[0],x);
            if(c[u]) std::swap(rt[0],rt[1]),u=explore(rt[0],x);
            c[u]=1,rt[0]=u;
            while(rt[0]!=x) {
                u=explore(rt[0],x);
                c[u]=1,rt[0]=u;
            }
        }
    }
    if(dataType==2) {
        for(re int i=2;i<=n;i++) d[1].push_back(i);
        divide(1);
        return;
    }
    rt=1;for(re int i=1;i<n;i++)p[i]=i+1;
    srand(time(0));std::random_shuffle(p+1,p+n);
    for(re int i=1;i<n;i++) if(!c[p[i]]) ins(p[i]);
}

[WC2018] 即时战略

原文:https://www.cnblogs.com/asuldb/p/12182816.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!