bzoj3545: [ONTAK2010]Peaks 重构树 主席树

题目链接

bzoj3545: [ONTAK2010]Peaks

题解

套路重构树上主席树

代码

#include<cstdio> 
#include<algorithm> 
#define gc getchar
#define pc putchar
inline int read() { 
	int x = 0,f = 1; 
	char c = getchar(); 
	while(c < '0' || c > '9') { if(c == '-')f = -1; c = gc(); } 
	while(c <= '9' && c >= '0') x = x * 10 + c - '0',c = gc(); 
	return x * f; 
} 
void print(int x) { 
	if(x < 0) { 
		pc('-'); 
		x = -x; 
	} 
	if(x >= 10) print(x / 10); 
	pc(x % 10 + '0'); 
} 
int n,m,q; 
const int maxn = 500007; 
int h[maxn]; 
struct node { 
	int u,v,w,next; 
} e[maxn],edge[maxn]; 
int num = 0,head[maxn]; 
inline void add_edge(int u,int v) { 
	edge[++ num].v = v; edge[num].next = head[u],head[u] = num; 
} 
inline bool cmp(node a,node b) { 
	return a.w < b.w; 
} 
int fa[maxn]; 
int dad[maxn][23],mn[maxn]; 
int tot = 0; 
int L[maxn],R[maxn]; 
int rt[maxn]; 
int lin[maxn],cnt = 0; 
void dfs(int x) { 
	L[x] = 0x3f3f3f3f; 
	R[x] = 0; 
	if(!head[x]) { 
		lin[++ cnt] = x; 
		L[x] = R[x] = cnt; 
		return; 
	} 
	for(int i = head[x];i ;i = edge[i].next) { 
		int v = edge[i].v; 
		dfs(v); 
		L[x] = std::min(L[v],L[x]); 
		R[x] = std::max(R[v],R[x]); 
	} 
} 

int b[maxn]; 
int sum = 0; 
struct Cmt { 
	int ls[100000 * 20],rs[100000 * 20],siz[100000 * 20];  
	void insert(int px,int &x,int l,int r,int k) { 
		x = ++ sum; 
		siz[x] = siz[px] + 1; 
		if(l == r) return; 
		ls[x] = ls[px], rs[x] = rs[px]; 
		int mid = l + r >> 1; 
		if(k <= mid) insert(ls[px],ls[x],l,mid,k); 
		else insert(rs[px],rs[x],mid + 1,r,k); 
	} 
	int query(int lx,int rx,int l,int r,int k) { 
		if(l == r) return l; 
		int mid = l + r >> 1, tmp = siz[rs[rx]] - siz[rs[lx]]; 
		if(tmp >= k) return query(rs[lx],rs[rx],mid + 1,r,k); 
		else return query(ls[lx],ls[rx],l,mid,k - tmp); 
	} 
} t; 
int get(int x,int val) { 
	for(int i = 20;i >= 0;-- i) 
		if(mn[dad[x][i]] <= val) 
		x = dad[x][i];
	return x; 
} 
int find(int x) { 
	if(fa[x] != x) fa[x] = find(fa[x]); 
	return fa[x]; 
} 
int main() { 
	mn[0] = 0x3f3f3f3f; 
	n = read(); m = read(); q = read(); 
	for(int i = 1;i <= n;++ i) b[i] = h[i] = read(); 
	std::sort(b + 1,b + n + 1); 
	int len = std::unique(b + 1,b + n + 1) - b - 1; 
	
	for(int i = 1;i <= n;++ i) h[i] = std::lower_bound(b + 1,b + len + 1,h[i]) - b; 
	
	for(int i = 1;i <= m;++ i) 
		e[i].u = read(),e[i].v = read(),e[i].w = read(); 
	tot = n; 
	for(int i = 1;i <= n;++ i) fa[i] = i;  
	std::sort(e + 1,e + m + 1,cmp); 
	int nnn = 0; 
	for(int i = 1;i <= m;++ i) { 
		int u = e[i].u,v = e[i].v; 
		int fu = find(u),fv = find(v); 
		if(fu != fv) { 
			++ tot; 
			dad[fu][0] = tot; 
			dad[fv][0] = tot; 
			add_edge(tot,fu); 
			add_edge(tot,fv); 
			fa[fu] = tot; 
			fa[fv] = tot; 
			fa[tot] = tot; 
			mn[tot] = e[i].w; 
			nnn ++; 
		} 
		if(nnn == n - 1) break; 
	} 
	for(int i = 1;i <= 20;++ i) 
		for(int j = 1;j <= tot; ++ j) 
			dad[j][i] = dad[dad[j][i - 1]][i - 1]; 
	//print(dad[15][0]);  
	dfs(tot); 
	for(int i = 1;i <= cnt;++ i) 
		t.insert(rt[i - 1],rt[i],1,len,h[lin[i]]); 
	for(int i = 1;i <= q;++ i) { 
		int v = read(),x = read(),k = read(); 
		int p = v; 
		v = get(v,x); 
		if(R[v] - L[v] + 1 < k) puts("-1"); 
		else print(b[t.query(rt[L[v] - 1],rt[R[v]],1,len,k)]),pc('\n');  
	} 
	return 0; 
} 
/*

*/
posted @ 2018-09-18 21:28  zzzzx  阅读(115)  评论(0编辑  收藏  举报