【LOJ】#3031. 「JOISC 2019 Day1」聚会

LOJ#3031. 「JOISC 2019 Day1」聚会

听说随机可过?

我想了很久想了一个不会被卡的做法,建出前\(u - 1\)个点的虚树,然后找第\(u\)个点的插入位置,就是每次找一条最长链,询问链的两个端点和u的虚树,如果u在链上那么二分找出u的位置,如果u不在链上且和链相连的点不在链上,那么建出那个点然后连上u,否则删除整条链,保留与u相连的那个点,继续这个操作

二分的代价应该最多是11,每次差不多删掉两个儿子是18/2 = 9

然而这个上限肯定跑不到,最后实测操作次数最多的数据点是21000+,有几个点19000,更多的在10000左右

还有一个2000的点跑了1998不知道发生了什么

#include "meetings.h"
#include <bits/stdc++.h>
#define fi first
#define se second
#define pii pair<int,int>
#define mp make_pair
#define pb push_back
#define space putchar(' ')
#define enter putchar('\n')
#define eps 1e-10
#define MAXN 2005
#define ba 47
//#define ivorysi
using namespace std;
typedef long long int64;
typedef unsigned int u32;
typedef double db;
template<class T>
void read(T &res) {
    res = 0;T f = 1;char c = getchar();
    while(c < '0' || c > '9') {
    if(c == '-') f = -1;
    c = getchar();
    }
    while(c >= '0' && c <= '9') {
    res = res * 10 +c - '0';
    c = getchar();
    }
    res *= f;
}
template<class T>
void out(T x) {
    if(x < 0) {x = -x;putchar('-');}
    if(x >= 10) {
    out(x / 10);
    }
    putchar('0' + x % 10);
}
set<int> to[2005];
bool vis[2005],finish[2005];
int dep[2005],S,T,fa[2005];
vector<int> v,line;
void getpos(int u,int fa) {
    v.pb(u);
    for(auto v : to[u]) {
    if(vis[v]) continue;
    if(v != fa) getpos(v,u);
    }
}
void dfs(int u) {
    for(auto v : to[u]) {
    if(v != fa[u]) {
        dep[v] = dep[u] + 1;
        fa[v] = u;
        dfs(v);
    }
    }
}
void getpara(int p) {
    v.clear();
    getpos(p,-1);
    dep[p] = 0;fa[p] = -1;
    dfs(p);
    S = p;
    for(auto t : v) {
    if(dep[t] > dep[S]) S = t;
    }
    dep[S] = 0;fa[S] = -1;
    dfs(S);
    T = p;
    for(auto t : v) {
    if(dep[t] > dep[T]) T = t;
    }
}
void pass_line(int a,int b) {
    dep[a] = 0;fa[a] = -1;
    dfs(a);
    int p = b;
    while(1) {
    vis[p] = 1;
    if(p == a) break;
    p = fa[p];
    }
}
void getline(int a,int b) {
    line.clear();
    dep[a] = 0;fa[a] = -1;
    dfs(a);
    int p = b;
    while(1) {
    line.pb(p);
    if(p == a) break;
    p = fa[p]; 
    }
}
void build(int u) {
    memset(vis,0,sizeof(vis));
    finish[u] = 1;
    int p = 0;
    while(1) {
    getpara(p);
    if(S == T) {
        to[S].insert(u);to[u].insert(S);break;
    }
    int m = Query(u,S,T);
    getline(S,T);
    bool f = 0;
    for(auto v : line) {
        if(v == m) {f = 1;break;}
    }
    if(!f && m != u) {
        build(m);to[m].insert(u);to[u].insert(m);break;
    }
    if(m == S) {to[u].insert(S);to[S].insert(u);break;}
    if(m == T) {to[u].insert(T);to[T].insert(u);break;}
    if(m == u) {
        
        int l = 1,r = line.size() - 1;
        while(l < r) {
        int mid = (l + r) >> 1;
        if(Query(u,line[mid],line[0]) == u) r = mid;
        else l = mid + 1;
        }
        int a = line[r],b = line[r - 1];
        to[b].erase(a);to[a].erase(b);
        to[b].insert(u);to[a].insert(u);
        to[u].insert(a);to[u].insert(b);
        break;
    }
    p = m;pass_line(S,T);vis[p] = 0;
    }
}
void Solve(int N) {
    to[0].insert(1);to[1].insert(0);
    for(int i = 2 ; i < N ; ++i) {
    if(!finish[i]) build(i);
    }
    for(int i = 0 ; i < N ; ++i) {
    for(auto v : to[i]) {
        if(v > i) Bridge(i,v);
    }
    }
}

猜你喜欢

转载自www.cnblogs.com/ivorysi/p/10947459.html