• CF487E Tourists 【圆方树 + 树剖 + 堆】


    题目链接

    CF487E

    题解

    圆方树 + 树剖 裸题
    建好圆方树维护路径上最小值即可
    方点的值为其儿子的最小值,这个用堆维护
    为什么只维护儿子?因为这样修改点的时候就只需要修改其父亲的堆
    这样充分利用了一对一的特性优化了复杂度
    如此询问时如果(lca)为方点,再询问一下(lca)的父亲即可
    复杂度(O(qlog^2n))

    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<queue>
    #include<cmath>
    #include<vector>
    #include<map>
    #define Redge(u) for (int k = h[u],to; k; k = ed[k].nxt)
    #define REP(i,n) for (int i = 1; i <= (n); i++)
    #define mp(a,b) make_pair<int,int>(a,b)
    #define cls(s) memset(s,0,sizeof(s))
    #define cp pair<int,int>
    #define LL long long int
    #define ls (u << 1)
    #define rs (u << 1 | 1)
    using namespace std;
    const int maxn = 200005,maxm = 100005,INF = 1000000000;
    inline int read(){
    	int out = 0,flag = 1; char c = getchar();
    	while (c < 48 || c > 57){if (c == '-') flag = -1; c = getchar();}
    	while (c >= 48 && c <= 57){out = (out << 3) + (out << 1) + c - 48; c = getchar();}
    	return out * flag;
    }
    int hh[maxn],nne = 1,h[maxn],ne = 1;
    struct EDGE{int to,nxt;}ed[maxn << 1],e[maxn << 1];
    inline void build(int u,int v){
    	e[++nne] = (EDGE){v,hh[u]}; hh[u] = nne;
    	e[++nne] = (EDGE){u,hh[v]}; hh[v] = nne;
    }
    inline void add(int u,int v){
    	ed[++ne] = (EDGE){v,h[u]}; h[u] = ne;
    	ed[++ne] = (EDGE){u,h[v]}; h[v] = ne;
    }
    struct HEAP{
    	priority_queue<int,vector<int>,greater<int> > a,b;
    	void ck(){while (!b.empty() && a.top() == b.top()) a.pop(),b.pop();}
    	int size(){return a.size() - b.size();}
    	void ins(int x){a.push(x);}
    	void del(int x){b.push(x);}
    	int top(){ck(); return size() ? a.top() : INF;}
    }H[maxn];
    int n,m,q,N,w[maxn];
    int dfn[maxn],low[maxn],st[maxn],Top,cnt;
    void dfs(int u,int las){
    	dfn[u] = low[u] = ++cnt; st[++Top] = u;
    	for (int k = hh[u],to; k; k = e[k].nxt)
    		if (k != las){
    			if (!dfn[to = e[k].to]){
    				dfs(to,k ^ 1);
    				low[u] = min(low[u],low[to]);
    				if (low[to] >= dfn[u]){
    					add(++N,u);
    					do{add(N,st[Top]);} while (st[Top--] != to);
    				}
    			}
    			else low[u] = min(low[u],dfn[to]);
    		}
    }
    int siz[maxn],top[maxn],dep[maxn],fa[maxn],son[maxn],id[maxn],Hash[maxn],Cnt;
    void dfs1(int u){
    	siz[u] = 1;
    	Redge(u) if ((to = ed[k].to) != fa[u]){
    		fa[to] = u; dep[to] = dep[u] + 1;
    		dfs1(to);
    		if (u > n) H[u - n].ins(w[to]);
    		siz[u] += siz[to];
    		if (!son[u] || siz[to] > siz[son[u]]) son[u] = to;
    	}
    	if (u > n) w[u] = H[u - n].top();
    }
    void dfs2(int u,int flag){
    	top[u] = flag ? top[fa[u]] : u;
    	id[u] = ++Cnt; Hash[Cnt] = u;
    	if (son[u]) dfs2(son[u],1);
    	Redge(u) if ((to = ed[k].to) != fa[u] && to != son[u])
    		dfs2(to,0);
    }
    int mn[maxn << 2];
    inline void upd(int u){mn[u] = min(mn[ls],mn[rs]);}
    void build(int u,int l,int r){
    	if (l == r){
    		mn[u] = w[Hash[l]];
    		return;
    	}
    	int mid = l + r >> 1;
    	build(ls,l,mid);
    	build(rs,mid + 1,r);
    	upd(u);
    }
    void modify(int u,int l,int r,int pos,int v){
    	if (l == r){mn[u] = v; return;}
    	int mid = l + r >> 1;
    	if (mid >= pos) modify(ls,l,mid,pos,v);
    	else modify(rs,mid + 1,r,pos,v);
    	upd(u);
    }
    int query(int u,int l,int r,int L,int R){
    	if (l >= L && r <= R) return mn[u];
    	int mid = l + r >> 1;
    	if (mid >= R) return query(ls,l,mid,L,R);
    	if (mid < L) return query(rs,mid + 1,r,L,R);
    	return min(query(ls,l,mid,L,R),query(rs,mid + 1,r,L,R));
    }
    int solve1(int u,int v){
    	int ans = INF;
    	while (top[u] != top[v]){
    		if (dep[top[u]] < dep[top[v]]) swap(u,v);
    		ans = min(ans,query(1,1,N,id[top[u]],id[u]));
    		u = fa[top[u]];
    	}
    	if (dep[u] > dep[v]) swap(u,v);
    	ans = min(ans,query(1,1,N,id[u],id[v]));
    	if (u > n && fa[u]) ans = min(ans,w[fa[u]]);
    	return ans;
    }
    void solve2(int u,int v){
    	modify(1,1,N,id[u],v);
    	if (fa[u]){
    		H[fa[u] - n].del(w[u]),H[fa[u] - n].ins(v);
    		w[fa[u]] = H[fa[u] - n].top();
    		modify(1,1,N,id[fa[u]],w[fa[u]]);
    	}
    	w[u] = v;
    }
    int main(){
    	N = n = read();  m = read(); q = read();
    	for (int i = 1; i <= n; i++) w[i] = read();
    	for (int i = 1; i <= m; i++) build(read(),read());
    	dfs(1,0);
    	dfs1(1);
    	dfs2(1,0);
    	build(1,1,N);
    	char opt; int a,b;
    	while (q--){
    		opt = getchar(); while (opt != 'A' && opt != 'C') opt = getchar();
    		a = read(); b = read();
    		if (opt == 'A') printf("%d
    ",solve1(a,b));
    		else solve2(a,b);
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    函数与宏定义实验报告
    C语言作业3
    循环结构课后反思
    C语言作业2
    C程序设计实验报告
    百分制成绩五级分制输出--二次作业
    第九章 结构体与共用体
    第八章 指针实验
    第七章 数组实验
    第六章 函数和宏定义实验(2)
  • 原文地址:https://www.cnblogs.com/Mychael/p/9203037.html
Copyright © 2020-2023  润新知