zoukankan      html  css  js  c++  java
  • CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    CF487E Tourists(圆方树+树链剖分+multiset/可删堆)

    Luogu

    给出一个带点权的无向图,两种操作:

    1、修改某点点权。

    2、询问x到y之间简单路径能走过的点的最小点权。

    题解时间

    总感觉是将一堆水题拼出来的丑陋产物(划去)

    毫无疑问看题直接搞上圆方树。

    用可删堆或者multiset维护方点的权值。

    查询直接树剖搞。

    但这样会发现修改时间复杂度无法保证。

    所以改成每个方点只记录子节点的权值。

    当lca为方点时答案计算一下它上面的圆点。

    $ O(nlog^{2}n) $

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #include<iostream>
    using namespace std;
    typedef long long lint;
    template<typename TP>inline void read(TP &tar)
    {
    	TP ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){ret=ret*10+ch-'0';ch=getchar();}
    	tar=ret*f;
    }
    namespace RKK
    {
    const int N=200011;
    struct superheap
    {
    	priority_queue<int> q0,q1;
    	int size;
    	int top(){update();return -q0.top();}
    	void push(int x){q0.push(-x),size++;}
    	void del(int x){q1.push(-x),size--;}
    	void update(){while(!q1.empty()){if(q0.top()==q1.top()) q0.pop(),q1.pop();else break;}}
    };
    int n,nn,m,qaq;
    struct segtree
    {
    	int v[N<<2];
    	void edit(int x,int w,int px=1,int pl=1,int pr=nn)
    	{
    		if(pl==pr){v[px]=w;return;}
    		int pm=pl+pr>>1;
    		if(x<=pm) edit(x,w,px<<1,pl,pm);
    		else edit(x,w,px<<1|1,pm+1,pr);
    		v[px]=min(v[px<<1],v[px<<1|1]);
    	}
    	int query(int l,int r,int px=1,int pl=1,int pr=nn)
    	{
    		if(l<=pl&&r>=pr) return v[px];
    		int ret=1145149961;
    		int pm=pl+pr>>1;
    		if(l<=pm) ret=min(ret,query(l,r,px<<1,pl,pm));
    		if(r>pm) ret=min(ret,query(l,r,px<<1|1,pm+1,pr));
    		return ret;
    	}
    };
    struct sumireko{int to,ne;};
    int w[N];
    int dfn[N],low[N],da;
    int sta[N],stp;
    int fa[N],dep[N],sz[N],dson[N],top[N],id[N];
    superheap heap[N];
    segtree sgt;
    struct graph
    {
    	sumireko e[N<<1];
    	int he[N],ecnt;
    	void addline(int f,int t){e[++ecnt].to=t;e[ecnt].ne=he[f],he[f]=ecnt;}
    	void tj(int x,graph *g)
    	{
    		dfn[x]=low[x]=++da,sta[++stp]=x;
    		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)
    		{
    			if(!dfn[t])
    			{
    				tj(t,g),low[x]=min(low[x],low[t]);
    				if(low[t]>=dfn[x])
    				{
    					nn++;int px=0;
    					while(px!=t)
    					{
    						px=sta[stp--];
    						g->addline(px,nn),g->addline(nn,px);
    					}
    					g->addline(x,nn),g->addline(nn,x);
    				}
    			}else low[x]=min(low[x],dfn[t]);
    		}
    	}
    	void dfs(int x)
    	{
    		sz[x]=1;
    		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(t!=fa[x])
    		{
    			fa[t]=x,dep[t]=dep[x]+1,dfs(t),sz[x]+=sz[t];
    			if(x>n) heap[x].push(w[t]);
    			if(sz[t]>sz[dson[x]]) dson[x]=t;
    		}
    	}
    	void dfs(int x,int tp)
    	{
    		if(x>n) w[x]=heap[x].top();
    		top[x]=tp,id[x]=++da,sgt.edit(id[x],w[x]);
    		if(dson[x]) dfs(dson[x],tp);
    		for(int i=he[x],t=e[i].to;i;i=e[i].ne,t=e[i].to)if(t!=fa[x]&&t!=dson[x])
    			dfs(t,t);
    	}
    }g1,g2;
    void getans(int x,int y)
    {
    	int ans=1145149961;
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]]) swap(x,y);
    		ans=min(ans,sgt.query(id[top[x]],id[x]));
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y]) swap(x,y);
    	ans=min(ans,sgt.query(id[x],id[y]));
    	if(x>n) ans=min(ans,w[fa[x]]);
    	printf("%d
    ",ans);
    }
    char op[5];
    int Iris()
    {
    	read(n),read(m),read(qaq),nn=n;
    	for(int i=1;i<=n;i++) read(w[i]);
    	for(int i=1,x,y;i<=m;i++) read(x),read(y),g1.addline(x,y),g1.addline(y,x);
    	g1.tj(1,&g2);
    	g2.dfs(1),da=0,g2.dfs(1,1);
    	for(int rkk=1,x,y;rkk<=qaq;rkk++)
    	{
    		scanf("%s",op),read(x),read(y);
    		switch(op[0])
    		{
    		case 'A':
    			getans(x,y);
    			break;
    		case 'C':
    			sgt.edit(id[x],y);
    			if(fa[x])
    			{
    				int px=fa[x];
    				heap[px].del(w[x]);
    				heap[px].push(y);
    				if(heap[px].top()!=w[px])
    				{
    					sgt.edit(id[px],heap[px].top());
    					w[px]=heap[px].top();
    				}
    			}
    			w[x]=y;
    			break;
    		}
    	}
    	return 0;
    }
    }
    int main(){return RKK::Iris();}
    
  • 相关阅读:
    JavaScript的continue、break和return的区别
    JavaScript的函数和作用域闭包
    利用反射快速给Model实体赋值
    C# 多态的实现
    C# 去除字符串首尾字符或字符串
    C#中大List的内存分配
    C#实现对图片文件的压缩、裁剪操作实例
    StringBuilder String string.Concat 字符串拼接速度
    C# 事件浅析
    理解 Thread.Sleep 函数
  • 原文地址:https://www.cnblogs.com/rikurika/p/12099163.html
Copyright © 2011-2022 走看看