zoukankan      html  css  js  c++  java
  • ●BZOJ 3545 [ONTAK2010]Peaks(离线)

    题链:

    http://www.lydsy.com/JudgeOnline/problem.php?id=3545

    http://www.lydsy.com/JudgeOnline/problem.php?id=3551(同题,强制在线,题解)

    题解:

    最小生成树 Kruskal,线段树(合并),离线
    首先把询问和边放在一起,按权值大小从小到大排序。
    然后对每个点建一棵权值线段树,维护当前联通块里的海拔权值区间内的山的个数
    然后按照 Kruskal 算法合并联通块,并且合并两个联通块对应的线段树(Merge操作看代码,感觉很暴力)。
    然后对于一个枚举到的询问,其起点所在的联通块里的点一定是可以到达的,
    所以就用线段树查询该联通块里的第k高的山就好了。

    代码:

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define MAXN 100500
    using namespace std;
    struct Oper{
    	int type,w,a,b;
    	bool operator <(const Oper &rtm) const{
    		if(w!=rtm.w) return w<rtm.w;
    		return type<rtm.type;
    	}
    }O[MAXN*10];
    struct SGT{
    	int rt[MAXN],ls[MAXN*50],rs[MAXN*50],cnt[MAXN*50],sz;
    	void Modify(int &u,int l,int r,int p){
    		if(!u) u=++sz;
    		if(l==r){cnt[u]++; return;}
    		int mid=(l+r)>>1; cnt[u]++;
    		if(p<=mid) Modify(ls[u],l,mid,p); 
    		else Modify(rs[u],mid+1,r,p);
    	}
    	int Merge(int u,int v){
    		if(!u||!v) return u+v;
    		cnt[u]+=cnt[v];
    		ls[u]=Merge(ls[u],ls[v]);
    		rs[u]=Merge(rs[u],rs[v]);
    		return u;
    	}
    	int Query(int u,int l,int r,int p){
    		if(l==r) return l;
    		int mid=(l+r)>>1;
    		if(p<=cnt[rs[u]]) return Query(rs[u],mid+1,r,p);
    		else return Query(ls[u],l,mid,p-cnt[rs[u]]);
    	}
    }T;
    int Fa[MAXN],H[MAXN],ANS[5*MAXN];
    int N,M,Q,Ont;
    void read(int &x){
    	static int f; static char ch;
    	x=0; f=1; ch=getchar();
    	while(ch<'0'||'9'<ch){if(ch=='-') f=-1; ch=getchar();}
    	while('0'<=ch&&ch<='9'){x=x*10+ch-'0'; ch=getchar();}
    	x=x*f;
    }
    int find(int x){
    	return x==Fa[x]?x:Fa[x]=find(Fa[x]);
    }
    int main(){
    	static int tmp[MAXN],tnt=0;
    	read(N); read(M); read(Q);
    	for(int i=1;i<=N;i++) 
    		Fa[i]=i,read(H[i]),tmp[++tnt]=H[i];
    	for(int i=1;i<=M;i++) 
    		read(O[++Ont].a),read(O[Ont].b),read(O[Ont].w),O[Ont].type=0;
    	for(int i=1;i<=Q;i++)
    		read(O[++Ont].a),read(O[Ont].w),read(O[Ont].b),O[Ont].type=i;
    	sort(tmp+1,tmp+tnt+1); tnt=unique(tmp+1,tmp+tnt+1)-tmp-1;
    	for(int i=1;i<=N;i++) 
    		H[i]=lower_bound(tmp+1,tmp+tnt+1,H[i])-tmp,
    		T.Modify(T.rt[i],1,tnt,H[i]);
    	sort(O+1,O+Ont+1);
    	for(int i=1,f,fa,fb,p;i<=Ont;i++){
    		if(O[i].type){
    			f=find(O[i].a);
    			if(T.cnt[T.rt[f]]<O[i].b) 
    				ANS[O[i].type]=-1;
    			else p=T.Query(T.rt[f],1,tnt,O[i].b),ANS[O[i].type]=tmp[p];
    		}
    		else{
    			fa=find(O[i].a); fb=find(O[i].b);
    			if(fa==fb) continue; Fa[fb]=fa;
    			T.rt[fa]=T.Merge(T.rt[fa],T.rt[fb]);
    		}
    	}
    	for(int i=1;i<=Q;i++) printf("%d
    ",ANS[i]);
    	return 0;
    }

  • 相关阅读:
    HDU 4691
    cin和scanf的速度差别
    一点点webservice的小知识
    Geetest 极验验证 验证图片拼图
    web api post传一个参数时 值永远是null
    关于支付宝支付的
    发布网站后只能在服务器上访问 外网访问不了??
    sidePagination: "server"和responseHandler: responseHandler
    .net 找回密码的第一步 第二步 第三步的进程条
    关于设置一个全局只读变量来实现验证
  • 原文地址:https://www.cnblogs.com/zj75211/p/8065794.html
Copyright © 2011-2022 走看看