zoukankan      html  css  js  c++  java
  • CF487 E. Tourists [点双连通分量 树链剖分 割点]

    E. Tourists

    题意:

    无向连通图

    • C a w: 表示 a 城市的纪念品售价变成 w。
    • A a b: 表示有一个游客要从 a 城市到 b 城市,你要回答在所有他的旅行路径中最低售价的最低可能值。

    (1≤n,m,q≤10^5,1≤w_ile10^9)


    显然一个点双连通分量中想去任何点都是可以的。

    那么bcc缩点,树剖一下就好了?

    割点可以存在于多个bcc!

    所以把割点单独拿出来,向每个bcc连边


    修改割点的权值怎么办?

    每个割点的信息合并到父亲bcc里,查询的时候lca为bcc那么额外加上父亲割点的信息就行了


    同一个bcc以及孩子割点还要用个multiset维护才能字词修改...


    然后吐槽一下bcc,行为真的很奇怪啊,甚至(u—v)这样的东西都会当做一个bcc...

    写+调了4个多小时…6.5kb...到半夜12:15,然后今天11点才起床没去上学2333

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define fir first
    #define sec second
    const int N = 2e5+5, inf = 1e9+5;
    inline int read() {
        char c=getchar(); int x=0,f=1;
        while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();}
        while(c>='0'&&c<='9') {x=x*10+c-'0';c=getchar();}
        return x*f;
    }
    
    int n, m, Q, w[N], x, y, lim;
    char s[N];
    struct meow {int u, v;} g[N];
    
    namespace ufs {
    	int fa[N];
    	int find(int x) {return x == fa[x] ? x : fa[x] = find(fa[x]);}
    } using ufs::find;
    
    struct edge {int v, ne;} e[N<<1];
    int cnt, h[N];
    map<int, int> has[N];
    inline void ins(int u, int v) {
        if(has[u][v]) return; has[u][v] = 1;
        if(find(u) == find(v)) return;
        //printf("ins %d %d
    ", u, v);
    	ufs::fa[find(u)] = find(v);
    	e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
    	e[++cnt] = (edge) {u, h[v]}; h[v] = cnt;
    }
    inline void link(int u, int v) {ins(u, v);}
    namespace G {
    	struct edge {int v, ne;} e[N<<1];
    	int cnt, h[N];
    	inline void ins(int u, int v) {
    		e[++cnt] = (edge) {v, h[u]}; h[u] = cnt;
    		e[++cnt] = (edge) {u, h[v]}; h[v] = cnt;
    	}
    	int dfn[N], low[N], dfc, is_cut[N], bel[N], bcc, bcc_size[N];
    	struct meow {int u, v;} st[N]; int top;
    	void dfs(int u, int fa) {
    		dfn[u] = low[u] = ++dfc;
    		int child = 0;
    		for(int i=h[u]; i; i=e[i].ne) {
    			int v = e[i].v;
    			if(v == fa) continue;
    			meow cur_edge = (meow){u, v};
    			if(!dfn[v]) {
    				st[++top] = cur_edge;
    				child++;
    				dfs(v, u);
    				low[u] = min(low[u], low[v]);
    				if(low[v] >= dfn[u]) {
    					is_cut[u] = true;
    					bcc++;
    					while(true) {
    						meow x = st[top--];
    						if(bel[x.u] != bcc) {
                                bel[x.u] = bcc, bcc_size[bcc]++;
                                if(is_cut[x.u]) link(n+bcc, x.u);
                            }
    						if(bel[x.v] != bcc) {
                                bel[x.v] = bcc, bcc_size[bcc]++;
                                if(is_cut[x.v]) link(n+bcc, x.v);
                            }
    						if(x.u == u && x.v == v) break;
    					}
    				}
    			} else if(dfn[v] < dfn[u]) st[++top] = cur_edge, low[u] = min(low[u], dfn[v]);
    		}
    		if(fa == 0 && child == 1) is_cut[u] = false;
    	}
    }
    using G::is_cut; using G::bcc; using G::bel; using G::bcc_size;
    
    
    int root, no_cut = 1;
    multiset<int> q[N];
    
    void build_tree() {
    
    	//for(int i=1; i<=n<<1; i++) if(is_cut[i]) printf("cut %d
    ", i);
        for(int i=1; i<=n; i++) bel[i] += n;// printf("bel %d  %d
    ", i, bel[i]);
        using G::e; using G::h;
        for(int u=1; u<=n; u++) {
            if(is_cut[u]) {
                for(int i=h[u]; i; i=e[i].ne) {
                    int v = e[i].v;
                    if(!is_cut[v]) ins(bel[v], u);
                }
            } else q[bel[u]].insert(w[u]);// printf("insert %d  %d %d
    ", u, bel[u], w[u]);
        }
    	for(int i=1; i<=m; i++) {
    		int u = g[i].u, v = g[i].v; //printf("(%d, %d)   %d  %d
    ", u, v, find(u), find(v));
    		if(is_cut[u] && is_cut[v] && find(u) != find(v)) ins(u, v);
    	}
    	if(is_cut[1]) root = 1;
    	else root = bel[1];
    	for(int i=1; i<=n; i++) if(is_cut[i]) no_cut = 0;
    }
    
    int dfn[N], dfc, deep[N], top[N], fa[N], size[N], mx[N];
    void dfs(int u) {
    	size[u] = 1;
    	for(int i=h[u]; i; i=e[i].ne) {
    		int v = e[i].v;
    		if(v == fa[u]) continue;
    		fa[v] = u;
    		deep[v] = deep[u] + 1;
    		if(!is_cut[u] && is_cut[v]) q[u].insert(w[v]);
    		dfs(v);
    		size[u] += size[v];
    		if(size[v] > size[mx[u]]) mx[u] = v;
    	}
    }
    int val[N];
    void dfs(int u, int anc) {
    	dfn[u] = ++dfc; val[dfc] = w[u];
    	top[u] = anc;
    	if(mx[u]) dfs(mx[u], anc);
    	for(int i=h[u]; i; i=e[i].ne) {
    		int v = e[i].v;
    		if(v != fa[u] && v != mx[u]) dfs(v, v);
    	}
    }
    
    namespace seg_t {
    	#define lc x<<1
    	#define rc x<<1|1
    	#define mid ((l+r)>>1)
    	#define lson lc, l, mid
    	#define rson rc, mid+1, r
    	int t[N<<2];
    	void build(int x, int l, int r) {
    		if(l == r) t[x] = val[l];
    		else {
    			build(lson);
    			build(rson);
    			t[x] = min(t[lc], t[rc]);
    		}
    	}
    	void cha(int x, int l, int r, int p, int v) {
    		if(l == r) t[x] = v;
    		else {
    			if(p <= mid) cha(lson, p, v);
    			else cha(rson, p, v);
    			t[x] = min(t[lc], t[rc]);
    		}
    	}
    	int que(int x, int l, int r, int ql, int qr) {
    		if(ql <= l && r <= qr) return t[x];
    		else {
    			int ans = inf;
    			if(ql <= mid) ans = min(ans, que(lson, ql, qr));
    			if(mid < qr)  ans = min(ans, que(rson, ql, qr));
    			return ans;
    		}
    	}
    } using seg_t::cha; using seg_t::que;
    
    void bcc_cha(int id, int u, int ww) {
    	q[id].erase(q[id].find(w[u]));
    	w[u] = ww;
    	q[id].insert(w[u]);
    	w[id] = *q[id].begin();
    	if(!no_cut) cha(1, 1, dfc, dfn[id], w[id]);
    }
    void bcc_cha2(int id, int last_w, int now_w) { //printf("bbc_cha2 %d  %d %d
    ", id, last_w, now_w);
    	q[id].erase(q[id].find(last_w));
    	q[id].insert(now_w);
        //for(set<int>::iterator it = q[id].begin(); it != q[id].end(); it++) printf("%d ", *it); printf("  q
    ");
    	w[id] = *q[id].begin();
    	cha(1, 1, dfc, dfn[id], w[id]);
    }
    
    void change(int u, int ww) {
    	if(is_cut[u]) {
    		int last_w = w[u];
    		w[u] = ww, cha(1, 1, dfc, dfn[u], ww);
    		int f = fa[u]; //printf("f %d
    ", f);
    		if(f && !is_cut[f]) bcc_cha2(f, last_w, ww);
    	} else bcc_cha(bel[u], u, ww);
    }
    
    void query(int x, int y) {
    	if(x == y) {printf("%d
    ", w[x]); return;}
    	if(!is_cut[x]) x = bel[x];
    	if(!is_cut[y]) y = bel[y];
    	//printf("query %d %d
    ", x, y);
    	int ans = inf;
    	while(top[x] != top[y]) {
    		if(deep[top[x]] < deep[top[y]]) swap(x, y);
    		ans = min(ans, que(1, 1, dfc, dfn[top[x]], dfn[x]));
    		x = fa[top[x]];
    	}
    	if(dfn[x] > dfn[y]) swap(x, y);
    	ans = min(ans, que(1, 1, dfc, dfn[x], dfn[y]));
    	if(!is_cut[x] && fa[x]) ans = min(ans, w[fa[x]]);
    	printf("%d
    ", ans);
    }
    
    int main() {
    	freopen("in", "r", stdin);
    	n = read(); m = read(); Q = read();
    	for(int i=1; i<=n; i++) w[i] = read();
    	for(int i=1; i<=m; i++) g[i].u = read(), g[i].v = read(), G::ins(g[i].u, g[i].v);
        for(int i=1; i<=n<<1; i++) ufs::fa[i] = i;
    
    	G::dfs(1, 0);
    	build_tree();
    	if(no_cut) {
            w[n+1] = *q[n+1].begin();
    		for(int i=1; i<=Q; i++) {
    			scanf("%s", s); x = read(); y = read();
    			if(s[0] == 'C') bcc_cha(n+1, x, y);
    			else printf("%d
    ", x==y ? w[x] : w[n+1]);
    		}
    		return 0;
    	}
    
    	dfs(root); dfs(root, root);
        for(int i=1; i<=bcc; i++) w[i+n] = *q[i+n].begin(), val[dfn[i+n]] = w[i+n];
    	seg_t::build(1, 1, dfc); //puts("hi");
    
    	for(int i=1; i<=Q; i++) { //printf("
    --------Q----------- %d
    ", i);
    		scanf("%s", s); x = read(); y = read();
    		if(s[0] == 'C') change(x, y);
    		else query(x, y);
    	}
    }
    
    
  • 相关阅读:
    洛谷P2414 阿狸的打字机
    洛谷P4362 贪吃的九头龙
    洛谷P4198 楼房重建
    JSP九大对象
    关于ErrorPage
    通过自己制作网页解决几个简单问题的方法
    九项重要的职业规划提示(转自W3School )
    jquery 使用方法(转载)
    <script language = "javascript">, <script type = "text/javascript">和<script language = "application/javascript">(转)
    微软当年的浏览器之战
  • 原文地址:https://www.cnblogs.com/candy99/p/6855859.html
Copyright © 2011-2022 走看看