zoukankan      html  css  js  c++  java
  • CF487E Tourists

    圆方树的问题。
    调了挺久的。
    先把圆方树给建出来,然后考虑怎么求答案。
    那么一个方点代表一个点双,那自然是这个点双里的答案。
    考虑改变一个点时,把这个的点的父亲方点的平衡树里更改。
    这样保证复杂度。
    于是乎套上树剖,注意当两点\(lca\)为方点时,答案还要考虑该方点的父亲圆点。
    开始码,妥妥的码农题(也可能是我菜,码了\(200h\)

    CF487E Tourists
    #include<iostream>
    #include<cstdio>
    #include<set>
    #include<cstring>
    #include<stack>
    #define ll long long
    #define N 200005
    
    struct P{
    	int to,next;
    };
    
    struct Map{
    	P e[N];
    	int cnt,head[N];
    	Map(){
    		cnt = 0;
    		std::memset(head,0,sizeof(head));
    	}
    	inline void add(int x,int y){
    //		std::cout<<x<<" "<<y<<std::endl;
    		e[++cnt].to = y;
    		e[cnt].next = head[x];
    		head[x] = cnt;
    	}
    }A,T;
    
    int n,m,Q,w[N];
    
    int dfncnt,dfn[N],low[N],fcnt;	
    bool vis[N];
    
    std::stack<int>QWQ;
    
    inline void tarjan(int u){
    	dfn[u] = low[u] = ++dfncnt;
    	QWQ.push(u);
    	for(int i = A.head[u];i;i = A.e[i].next){
    		int v = A.e[i].to;
    		if(!dfn[v]){
    			tarjan(v);
    			low[u] = std::min(low[u],low[v]);
    			if(low[v] == dfn[u]){
    				++fcnt;
    				while(QWQ.top() != v){
    					T.add(fcnt,QWQ.top());
    					T.add(QWQ.top(),fcnt);
    					QWQ.pop();
    				}
    				T.add(fcnt,QWQ.top());
    				T.add(QWQ.top(),fcnt);
    				QWQ.pop();
    				T.add(fcnt,u);
    				T.add(u,fcnt);				
    			}
    		}
    		else
    		low[u] = std::min(low[u],dfn[v]);
    	}
    }
    
    int dep[N],siz[N],son[N],top[N],to[N],f[N];
    
    inline void dfs(int u,int fa){
    	f[u] = fa,siz[u] = 0,dep[u] = dep[fa] + 1;
    	for(int i = T.head[u];i;i = T.e[i].next){
    		int v = T.e[i].to;
    		if(v == fa)
    		continue;
    		dfs(v,u);
    		siz[u] += siz[v];
    		if(siz[v] > siz[son[u]])
    		son[u] = v;
    	}
    }
    
    inline void dfs2(int u,int f,int tp){
    	dfn[u] = ++dfncnt,to[dfn[u]] = u,top[u] = tp;
    	if(son[u])
    	dfs2(son[u],u,tp);
    	for(int i = T.head[u];i;i = T.e[i].next){
    		int v = T.e[i].to;
    		if(v == son[u] || v == f)
    		continue;
    		dfs2(v,u,v);
    	}
    }
    
    ll t[N << 2];
    
    #define mid ((l + r) >> 1)
    #define li (now << 1)
    #define ri ((now << 1) | 1)
    
    inline void build(int now,int l,int r){
    	if(l == r){
    		t[now] = w[to[l]];
    //		std::cout<<now<<" "<<l<<" "<<r<<" "<<t[now]<<std::endl;		
    		return;
    	}
    	build(li,l,mid);
    	build(ri,mid + 1,r);
    	t[now] = std::min(t[li],t[ri]);
    //	std::cout<<now<<" "<<l<<" "<<r<<" "<<t[now]<<std::endl;
    }
    
    inline void mdf(int now,int l,int r,int p,int x){
    	if(l == r){
    		t[now] = x;
    		return;
    	}
    	if(p <= mid)
    	mdf(li,l,mid,p,x);
    	else
    	mdf(ri,mid + 1,r,p,x);
    	t[now] = std::min(t[li],t[ri]);
    }
    
    inline ll q(int now,int l,int r,int tl,int tr){
    //	std::cout<<now<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<" "<<t[now]<<std::endl;
    	if(tl <= l && r <= tr)
    	return t[now];
    	ll ans = 0x3f3f3f3f;
    	if(tl <= mid)
    	ans = std::min(ans,q(li,l,mid,tl,tr));
    	if(tr > mid)
    	ans = std::min(ans,q(ri,mid + 1,r,tl,tr));
    	return ans;
    }
    
    std::multiset<int> s[N * 2];
    
    int main(){
    	scanf("%d%d%d",&n,&m,&Q);
    	fcnt = n;
    	for(int i = 1;i <= n;++i)
    	scanf("%d",&w[i]);
    	for(int i = 1;i <= m;++i){
    		int x,y;
    		scanf("%d%d",&x,&y);
    		A.add(x,y);
    		A.add(y,x);
    	}
    	for(int i = 1;i <= n;++i){
    		if(!dfn[i])
    		tarjan(i);
    	}
    	dfncnt = 0;
    	dfs(1,0);
    	dfs2(1,0,1);
    	for(int i = 1;i <= n;++i)
    	if(f[i])
    	s[f[i]].insert(w[i]);
    	for(int i = n + 1;i <= dfncnt;++i)
    	w[i] = *s[i].begin();
    	build(1,1,dfncnt);
    	while(Q -- ){
    		char a[3];
    		int x,y;
    		scanf("%s%d%d",a,&x,&y);
    		if(a[0] == 'C'){
    			if(f[x]){
    				s[f[x]].insert(y);
    				s[f[x]].erase(s[f[x]].lower_bound(w[x]));
    				if(w[f[x]] != *s[f[x]].begin()){
    					w[f[x]] = *s[f[x]].begin();
    					mdf(1,1,dfncnt,dfn[f[x]],w[f[x]]);
    				}
    			}
    			mdf(1,1,dfncnt,dfn[x],y);
    			w[x] = y;
    		}
    		if(a[0] == 'A'){
    			ll ans = 0x3f3f3f3f;
    			while(top[x] != top[y]){
    				if(dep[top[x]] < dep[top[y]])
    				std::swap(x,y);
    				ans = std::min(ans,q(1,1,dfncnt,dfn[top[x]],dfn[x]));
    				x = f[top[x]];
    			}
    //			std::cout<<ans<<std::endl;
    			if(dfn[x] > dfn[y])
    			std::swap(x,y);
    			ans = std::min(ans,q(1,1,dfncnt,dfn[x],dfn[y]));
    //			std::cout<<ans<<std::endl;
    			if(x > n)
    			ans = std::min(ans,(ll)w[f[x]]);
    			std::cout<<ans<<std::endl;
    		}
    	}
    }
    
    TLE on tese 29 不过实在是不想调了
  • 相关阅读:
    【12】简单SQL语句
    【11】分离与附加
    【10】约束
    CSS深入理解学习笔记之vertical-align
    CSS深入理解学习笔记之relative
    CSS深入理解学习笔记之z-index
    CSS深入理解学习笔记之margin
    CSS深入理解学习笔记之padding
    CSS深入理解学习笔记之border
    网页结构与表现原则
  • 原文地址:https://www.cnblogs.com/dixiao/p/14730349.html
Copyright © 2011-2022 走看看