• DISQUERY


    洛咕

    题意:给定有(n)个节点的树, 树上边有边权. 再给定(q)组询问, 每次询问两个点路径上的最小值和最大值.(n,q<=100000.)

    询问树上路径点权的最值是树链剖分的模板题,然后本题给的是边权,就化边权为点权,从1号点为根(dfs)的时候,把(w[u][v])这条边的边权给节点(v).然后就可以按照模板来做了(???)

    但是,这时根节点的权值为0,如果一条路径经过了根节点,其最小值会是根节点的权值0,所以我把根节点的权值赋值为(-1),然后维护线段树区间最小值取(min)操作的时候,特判(-1)的情况(自己写个(min)函数就好了),因为边权为正(虽然题目好像并没有说明,当做默认了),所以对最大值的答案是没有影响的.然后就可以按照模板来做了(???)

    但是,会发现连样例一的第一组询问都过不去,注意到如果一组询问((x,y)),设(lca=LCA(x,y)).查询答案的时候,(lca)的权值对答案产生了影响,因为这条路径会经过(lca),但是因为路径不会经过(lca)(fa[lca])这条边,所以实际上(lca)的权值是不能被考虑贡献的,所以我极其暴力地写了个线段树的单点修改操作,查询前把(lca)的权值改为(-1),查询后又改回来....

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline int read(){
        int x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=100005;
    int n,q,ans_min,ans_max,val[N],maxn[N<<2],minn[N<<2];
    int tot,head[N],nxt[N<<1],to[N<<1],w[N<<1];
    inline void add(int a,int b,int c){nxt[++tot]=head[a];head[a]=tot;to[tot]=b;w[tot]=c;}
    int size[N],dep[N],fa[N],son[N],seg[N],rev[N],top[N];//按理说,rev[]数组要开4倍的啊,莫非是数据水???
    inline void dfs1(int u,int father){
    	size[u]=1;
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];if(v==father)continue;
    		dep[v]=dep[u]+1;fa[v]=u;val[v]=w[i];
    		dfs1(v,u);size[u]+=size[v];
    		if(size[v]>size[son[u]])son[u]=v;
    	}
    }
    inline void dfs2(int u,int fa){
    	if(son[u]){
    		seg[son[u]]=++seg[0];
    		rev[seg[0]]=son[u];
    		top[son[u]]=top[u];
    		dfs2(son[u],u);
    	}
    	for(int i=head[u];i;i=nxt[i]){
    		int v=to[i];
    		if(!top[v]){
    			seg[v]=++seg[0];
    			rev[seg[0]]=v;
    			top[v]=v;dfs2(v,u);
    		}
    	}
    }
    inline int min(int x,int y){//手写min函数,特判-1情况
    	if(x==-1)return y;
    	if(y==-1)return x;
    	return x<=y?x:y;
    }
    inline void build(int p,int l,int r){
    	if(l==r){
    		maxn[p]=minn[p]=val[rev[l]];
    		return;
    	}
    	int mid=(l+r)>>1;
    	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
    	maxn[p]=max(maxn[p<<1],maxn[p<<1|1]);
    	minn[p]=min(minn[p<<1],minn[p<<1|1]);
    }
    inline void change(int p,int l,int r,int x,int v){
    	if(l==r&&l==x){minn[p]=maxn[p]=v;return;}
    	int mid=(l+r)>>1;
    	if(x<=mid)change(p<<1,l,mid,x,v);
    	else change(p<<1|1,mid+1,r,x,v);
    	maxn[p]=max(maxn[p<<1],maxn[p<<1|1]);
    	minn[p]=min(minn[p<<1],minn[p<<1|1]);
    }
    inline void query(int p,int l,int r,int ql,int qr){
    	if(ql<=l&&qr>=r){
    		ans_min=min(ans_min,minn[p]);
    		ans_max=max(ans_max,maxn[p]);
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(ql<=mid)query(p<<1,l,mid,ql,qr);
    	if(qr>mid)query(p<<1|1,mid+1,r,ql,qr);
    }
    inline void ask(int x,int y){	
    	while(top[x]!=top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		query(1,1,seg[0],seg[top[x]],seg[x]);
    		x=fa[top[x]];
    	}
    	if(dep[x]>dep[y])swap(x,y);
    	query(1,1,seg[0],seg[x],seg[y]);
    }
    inline int LCA(int x,int y){
        while(top[x]!=top[y]){
    		if(dep[top[x]]>=dep[top[y]])x=fa[top[x]];
    		else y=fa[top[y]];
        }
        return dep[x]<dep[y]?x:y;
    }
    int main(){
    	n=read();
    	for(int i=1;i<n;++i){
    		int a=read(),b=read(),c=read();
    		add(a,b,c);add(b,a,c);
    	}
    	dep[1]=seg[0]=seg[1]=rev[1]=top[1]=1;val[1]=-1;
    	dfs1(1,0);dfs2(1,0);build(1,1,seg[0]);q=read();
    	while(q--){
    		int x=read(),y=read(),lca=LCA(x,y);
    		change(1,1,seg[0],seg[lca],-1);
    		ans_min=1e9;ans_max=-1e9;ask(x,y);
    		printf("%d %d
    ",ans_min,ans_max);
    		change(1,1,seg[0],seg[lca],val[lca]);
    	}
        return 0;
    }
    
    
  • 相关阅读:
    AOC的服务还不错
    浅谈Java、MySQL的中文排序问题
    祝cnBlogs的Blogger们新年快乐!
    GT 3.9.4以及今天的工作
    堆排序
    桶排序
    常用排序算法稳定性分析
    VS2010远程调试环境配置详解
    基数排序
    如何修改数据库的服务器名称
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11720979.html
Copyright © 2020-2023  润新知