卧薪尝胆,厚积薄发。
ONTAK2010 Peaks
Date: Wed Oct 31 20:33:24 CST 2018 In Category: NoCategory

Description:

有 $N$ 座山峰,山峰有高度 $h_i$ 。共 $M$ 条路径,每条路径有一个困难值,现在有 $Q$ 组询问,询问从点 $v$ 开始只经过困难值小于等于 $x$ 的路径所能到达的山峰中第 $k$ 高的山峰。
$1\leqslant n\leqslant 10^5,1\leqslant m,q\leqslant 3\times 10^5$

Solution:

先把所有询问离线按 $x$ 排序,把边按困难值排序,然后每次把所有困难值比 $x$ 小的边都合并它们的两个端点,在同时维护一个权值线段树,合并时就做线段树合并,查询时在树上查第 $k$ 大即可。

Code:


#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cmath>
#include<cctype>
#include<cstring>
using namespace std;
#define R register
inline int rd()
{
R int res = 0,f = 1;
R char c = getchar();
while(!isdigit(c))
{
if(c == '-')f = -1;
c = getchar();
}
while(isdigit(c))
{
res = (res << 1) + (res << 3) + c - '0';
c = getchar();
}
return res * f;
}
int n,m,s;
#define MAXN 100010
int h[MAXN];
#define MAXM 500010
struct edges
{
int u,v,w;
}es[MAXM];
bool cmp_w(edges a,edges b){return a.w < b.w;}
struct query
{
int p,x,k,id;
}q[MAXM];
bool cmp_x(query a,query b){return a.x < b.x;}
int ans[MAXM];
struct node
{
int lc,rc;
int sum;
}t[MAXN * 33];
int ptr = 0;
int newnode(){return ++ptr;}
#define LE 0
#define RI 1000000000
#define mid ((l + r) >> 1)
int root[MAXN];
void insert(int &rt,int p,int l,int r)
{
rt = newnode();
++t[rt].sum;
if(l == r)return;
if(p <= mid)insert(t[rt].lc,p,l,mid);
else insert(t[rt].rc,p,mid + 1,r);
return;
}
int merge(int rtx,int rty,int l,int r)
{
if(rtx == 0 || rty == 0)return rtx + rty;
t[rtx].sum += t[rty].sum;
if(l == r)return rtx;
t[rtx].lc = merge(t[rtx].lc,t[rty].lc,l,mid);
t[rtx].rc = merge(t[rtx].rc,t[rty].rc,mid + 1,r);
return rtx;
}
int query(int rt,int k,int l,int r)
{
if(rt == 0)return -1;
if(t[rt].sum < k)return -1;
if(l == r)return l;
if(k <= t[t[rt].rc].sum)return query(t[rt].rc,k,mid + 1,r);
else return query(t[rt].lc,k - t[t[rt].rc].sum,l,mid);
}
int f[MAXN];
int find(int x){return (x == f[x] ? x : f[x] = find(f[x]));}
inline void collect(int a,int b)
{
int p = find(a),q = find(b);
if(p == q)return;
f[p] = q;
root[q] = merge(root[p],root[q],LE,RI);
return;
}
int main()
{
scanf("%d%d%d",&n,&m,&s);
for(R int i = 1;i <= n;++i)h[i] = rd();
for(R int i = 1;i <= n;++i)f[i] = i;
for(R int i = 1;i <= m;++i)
{
es[i].u = rd();es[i].v = rd();es[i].w = rd();
}
sort(es + 1,es + 1 + m,cmp_w);
for(R int i = 1;i <= s;++i)
{
q[i].p = rd();q[i].x = rd();q[i].k = rd();
q[i].id = i;
}
for(R int i = 1;i <= n;++i)insert(root[i],h[i],LE,RI);
sort(q + 1,q + 1 + s,cmp_x);
for(R int i = 1,j = 1;i <= s;++i)
{
while(j <= m && es[j].w <= q[i].x)
{
collect(es[j].u,es[j].v);
++j;
}
ans[q[i].id] = query(root[find(q[i].p)],q[i].k,LE,RI);
}
for(R int i = 1;i <= s;++i)printf("%d\n",ans[i]);
return 0;
}
Copyright © 2020 wjh15101051
ღゝ◡╹)ノ♡