• 【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('
    ')
    #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);
    	}
        }
    }
    
    
  • 相关阅读:
    关于 语文物理 和 数学物理
    黎耀天 共量子 我拍了 几张照片 给你们 当 素材
    看了 陈记抄 同学 的 《随便聊聊之量子力学中的散射理论》
    极坐标系 下的 牛顿第二定律
    jQuery 工具类库集锦
    Javascript跨域问题解决方案
    js禁止从浏览器缓存读取消息
    关于双击事件.MouseEvent.DOUBLE_CLICK
    div的打开与关闭js
    利用通道完成文件的复制 (非直接缓存区)
  • 原文地址:https://www.cnblogs.com/ivorysi/p/10947459.html
Copyright © 2020-2023  润新知