zoukankan      html  css  js  c++  java
  • CF487E Tourists(圆方树+堆+链剖)

    本题解并不提供圆方树讲解。
    所以不会圆方树的出门右转问yyb
    没有修改的话圆方树+链剖。
    方点的权值为点双连通分量里的最小值。
    然后修改的话圆点照修,每一个方点维护一个小根堆。
    考虑到可能被菊花卡死。
    我们每一个方点只维护儿子的最小值。
    当询问的路径(lca)为方点时,(ans=min(ans,w[fa[lca]]))即可。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    using namespace std;
    #define ls now<<1
    #define rs now<<1|1
    const int N=444444;
    struct queue{
    	priority_queue<int,vector<int>,greater<int> >q1;
    	priority_queue<int,vector<int>,greater<int> >q2;
    	void push(int x){q1.push(x);}
    	void del(int x){q2.push(x);}
    	int top(){
    		while(!q2.empty()&&q1.top()==q2.top())q1.pop(),q2.pop();
    		return q1.top();
    	}
    }q[N];
    struct Graph{
    	int cnt,head[N];
    	struct edge{
    		int to,nxt;
    	}e[N*2];
    	void add_edge(int u,int v){
    		cnt++;
    		e[cnt].nxt=head[u];
    		e[cnt].to=v;
    		head[u]=cnt;
    	}
    }g1,g2;
    int dfn[N],low[N],tim,stack[N],Top,num;
    void Tarjan(int u){
    	dfn[u]=low[u]=++tim;
    	stack[++Top]=u;
    	for(int i=g1.head[u];i;i=g1.e[i].nxt){
    		int v=g1.e[i].to;
    		if(dfn[v]==0){
    			Tarjan(v);
    			low[u]=min(low[v],low[u]);
    			if(low[v]>=dfn[u]){
    				g2.add_edge(++num,u);
    				g2.add_edge(u,num);
    				int x;
    				do{
    					x=stack[Top--];
    					g2.add_edge(num,x);
    					g2.add_edge(x,num);
    				}while(x!=v);
    			}
    		}
    		else low[u]=min(low[u],dfn[v]);
    	}
    }
    int fa[N],size[N],dep[N],son[N];
    int n,w[N];
    void dfs1(int u,int f){
    	fa[u]=f;
    	size[u]=1;
    	dep[u]=dep[f]+1;
    	for(int i=g2.head[u];i;i=g2.e[i].nxt){
    		int v=g2.e[i].to;
    		if(v==f)continue;
    		if(u>n)q[u].push(w[v]);
    		dfs1(v,u);
    		size[u]+=size[v];
    		if(size[son[u]]<=size[v])son[u]=v;
    	}
    }
    int top[N],id[N],tot;
    void dfs2(int u,int tp){
    	dfn[u]=++tot;
    	top[u]=tp;
    	id[tot]=u;
    	if(son[u])dfs2(son[u],tp);
    	for(int i=g2.head[u];i;i=g2.e[i].nxt){
    		int v=g2.e[i].to;
    		if(v==fa[u]||v==son[u])continue;
    		dfs2(v,v);
    	}
    }
    int mn[N*4];
    void update(int now){
    	mn[now]=min(mn[ls],mn[rs]);
    }
    void build(int l,int r,int now){
    	if(l==r){
    		if(id[l]<=n)mn[now]=w[id[l]];
    		else mn[now]=q[id[l]].top();
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(l,mid,ls);
    	build(mid+1,r,rs);
    	update(now);
    }
    void change(int l,int r,int x,int c,int now){
    	if(l==r){
    		mn[now]=c;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x>mid)change(mid+1,r,x,c,rs);
    	else change(l,mid,x,c,ls);
    	update(now);
    }
    int check(int l,int r,int L,int R,int now){
    	if(l==L&&r==R)return mn[now];
    	int mid=(l+r)>>1;
    	if(L>mid)return check(mid+1,r,L,R,rs);
    	else if(R<=mid)return check(l,mid,L,R,ls);
    	else return min(check(l,mid,L,mid,ls),check(mid+1,r,mid+1,R,rs));
    }
    int getlca(int x,int y){
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		x=fa[top[x]];
    	}
    	if(dep[x]<dep[y])return x;
    	else return y;
    }
    int checkroad(int x,int y){
    	int mn=-1;
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		if(mn==-1)mn=check(1,num,dfn[top[x]],dfn[x],1);
    		else mn=min(mn,check(1,num,dfn[top[x]],dfn[x],1));
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	if(mn==-1)mn=check(1,num,dfn[x],dfn[y],1);
    	else mn=min(mn,check(1,num,dfn[x],dfn[y],1));
    	return mn;
    }
    int read(){
    	int sum=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
    	return sum*f;
    }
    int Q,m;
    int main(){
    	n=read();m=read();Q=read();
    	num=n;
    	for(int i=1;i<=n;i++)w[i]=read();
    	for(int i=1;i<=m;i++){
    		int u=read(),v=read();
    		g1.add_edge(u,v);g1.add_edge(v,u);
    	}
    	Tarjan(1);
    	dfs1(1,0);
    	dfs2(1,1);
    	build(1,num,1);
    	char s[3];
    	while(Q--){
    		scanf("%s",s+1);
    		if(s[1]=='C'){
    			int x=read(),c=read();
    			if(dfn[x]!=1){
    				q[fa[x]].del(w[x]);
    				q[fa[x]].push(c);
    				change(1,num,dfn[fa[x]],q[fa[x]].top(),1);
    			}
    			w[x]=c;
    			change(1,num,dfn[x],c,1);
    		}
    		else{
    			int x=read(),y=read();
    			int lca=getlca(x,y);
    			int tmp=checkroad(x,y);
    			printf("%d
    ",lca<=n?tmp:min(tmp,w[fa[lca]]));
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Swagger使用总结
    idear常用快捷键
    Liunx下安装MongoDB
    python面向对象的特点,类定义等,私有属性、公有属性、成员属性
    Python,subprocess模块(补充)
    对称加密和非对称加密概述
    Python关于导入模块的一些感想:
    Python学习第二阶段Day2,模块subprocess、 logging、re
    Python学习第二阶段Day2(json/pickle)、 shelve、xml、PyYAML、configparser、hashlib模块
    Python学习第二阶段Day2,模块time/datetime、random、os、sys、shutil
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/10492774.html
Copyright © 2011-2022 走看看