zoukankan      html  css  js  c++  java
  • 并不对劲的bzoj4538:loj2049:p3250:[HNOI2016]网络

    题意

    有一棵(n)((nleq 10^5))个点的树,(m)((mleq 2 imes 10^5))个操作。操作有三种:1.给出(u,v,k),表示加入一条从(u)(v)权值为(k)的路径;2.给出(k),表示删除(k)时刻加入的路径;3.给出(x),表示询问不经过点(x)的路径的权值最大值。

    题解

    3操作看上去很奇怪,先假装它是“询问经过(x)的路径的权值最大值”。
    这样1操作就可以看成区间修改为最大值,3操作可以看成单点求值。注意这是不用pushdown的,因为线段树中一个点的值应该是所有祖先的tag的最大值。
    2操作是区间删一个数,那么可以在线段树的每个点维护一个可删堆,1操作变成向一个区间的点的堆中加一个数,2操作变成将一个区间的点的堆删一个数。
    这样之所以是对的,是因为没有pushdown或pushup,使1操作时涉及的区间和对应的2操作涉及的区间是相同的,不会有堆被删空。
    再考虑3操作。
    这时1、2操作影响的区域就由“这条路径上的点”变成了“不在这条路径上的点”,需要手动处理出 在这条路径上的点的区间 的补集。
    注意不能先将区间([1,n])区间加数再将这条路径上的点的区间删数,因为“将区间([1,n])区间加数”只会改线段树根节点的堆,而“将这条路径上的点的区间删数”会把某些点的堆大小删成负数。

    代码

    #include<algorithm>
    #include<cmath>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<ctime>
    #include<iomanip>
    #include<iostream>
    #include<map>
    #include<queue>
    #include<stack>
    #include<vector>
    #define LL long long
    #define rep(i,x,y) for(int i=(x);i<=(y);++i)
    #define dwn(i,x,y) for(int i=(x);i>=(y);--i)
    #define view(u,k) for(int k=fir[u];~k;k=nxt[k])
    #define maxn 100007
    #define maxm 200007
    #define mp make_pair
    #define fi first
    #define se second
    #define pb push_back
    #define pii pair<int,int>
    #define ls (u<<1)
    #define rs (u<<1|1)
    #define mi ((l+r)>>1) 
    #define fi first
    #define se second
    #define mp make_pair
    using namespace std;
    int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(!isdigit(ch)&&ch!='-')ch=getchar();
    	if(ch=='-')f=-1,ch=getchar();
    	while(isdigit(ch))x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    	return x*f;
    }
    void write(int x)
    {
    	char ch[20];int f=0;
    	if(!x){putchar('0'),putchar('
    ');return;}
    	if(x<0)putchar('-'),x=-x;
    	while(x)ch[++f]=x%10+'0',x/=10;
    	while(f)putchar(ch[f--]);
    	putchar('
    ');
    }
    struct deadque
    {
    	priority_queue<int>yes,no;
    	int top(){while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();return yes.top();}
    	int size(){return yes.size()-no.size();}
    	void push(int x){return yes.push(x);}
    	void del(int x){return no.push(x);} 
    }q[maxn<<2];
    int fir[maxn],nxt[maxm],v[maxm],cnte,qa[maxm],qb[maxm],qc[maxm];
    int n,m,dep[maxn],son[maxn],fa[maxn],top[maxn],siz[maxn],dfn[maxn],tim,num;
    pii b[maxn];
    void ade(int u1,int v1){v[cnte]=v1,nxt[cnte]=fir[u1],fir[u1]=cnte++;}
    void getson(int u)
    {
    	siz[u]=1;
    	view(u,k)if(v[k]!=fa[u])
    	{
    		fa[v[k]]=u,dep[v[k]]=dep[u]+1,getson(v[k]),siz[u]+=siz[v[k]];
    		if(!son[u]||siz[son[u]]<siz[v[k]])son[u]=v[k];
    	}
    }
    void gettop(int u,int anc)
    {
    	dfn[u]=++tim,top[u]=anc;
    	if(son[u])gettop(son[u],anc);
    	view(u,k)if(v[k]!=fa[u]&&v[k]!=son[u])gettop(v[k],v[k]); 
    }
    void add(int u,int l,int r,int x,int y,int k,int f)
    {
    	if(x<=l&&r<=y){if(f)q[u].push(k);else q[u].del(k);return;}
    	if(x<=mi)add(ls,l,mi,x,y,k,f);
    	if(y>mi)add(rs,mi+1,r,x,y,k,f);
    }
    int ask(int u,int l,int r,int x)
    {
    	if(x<=l&&r<=x){return q[u].size()==0?-1:q[u].top();}
    	int res=q[u].size()==0?-1:q[u].top();
    	if(x<=mi)return max(res,ask(ls,l,mi,x));
    	return max(res,ask(rs,mi+1,r,x));
    }
    void addrd(int x,int y,int k,int f)
    {
    	num=0;
    	while(top[x]!=top[y])
    	{
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		num++,b[num]=mp(dfn[top[x]],dfn[x]),x=fa[top[x]];
    	}
    	if(dep[x]<dep[y])swap(x,y);
    	num++,b[num]=mp(dfn[y],dfn[x]);
    	int lst=1;
    	sort(b+1,b+num+1);
    	rep(i,1,num)
    	{
    		if(lst<=b[i].fi-1)add(1,1,n,lst,b[i].fi-1,k,f);
    		lst=b[i].se+1;
    	}
    	if(lst<=n)add(1,1,n,lst,n,k,f);
    }
    int main()
    {
    	memset(fir,-1,sizeof(fir)); 
    	n=read(),m=read();
    	rep(i,1,n-1){int x=read(),y=read();ade(x,y),ade(y,x);}
    	getson(1),gettop(1,1);
    	rep(i,1,m)
    	{
    		int t=read();
    		if(t==0){qa[i]=read(),qb[i]=read(),qc[i]=read();addrd(qa[i],qb[i],qc[i],1);}
    		else if(t==1){int j=read();if(qa[j]==0)continue;addrd(qa[j],qb[j],qc[j],0);}
    		else{int x=read();write(ask(1,1,n,dfn[x]));}
    	}
    	return (0-0);
    }
    
  • 相关阅读:
    云计算和大数据时代网络技术揭秘(八)数据中心存储FCoE
    云计算和大数据时代网络技术揭秘(七)大二层网络
    云计算和大数据时代网络技术揭秘(六)LISP协议
    云计算和大数据时代网络技术揭秘(五)可靠的网络
    云计算和大数据时代网络技术揭秘(四)网络加密
    云计算和大数据时代网络技术揭秘(三)安全的网络准入
    python3练习100题——027
    python3练习100题——026
    python3练习100题——025
    python3练习100题--024
  • 原文地址:https://www.cnblogs.com/xzyf/p/11626461.html
Copyright © 2011-2022 走看看