您的位置:首页 > 其它

bzoj3545 [ONTAK2010]Peaks

2014-10-28 22:24 253 查看

3545: [ONTAK2010]Peaks

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 572 Solved: 164
[Submit][Status]

Description

在Bytemountains有N座山峰,每座山峰有他的高度h_i。有些山峰之间有双向道路相连,共M条路径,每条路径有一个困难值,这个值越大表示越难走,现在有Q组询问,每组询问询问从点v开始只经过困难值小于等于x的路径所能到达的山峰中第k高的山峰,如果无解输出-1。

Input

第一行三个数N,M,Q。
第二行N个数,第i个数为h_i
接下来M行,每行3个数a b c,表示从a到b有一条困难值为c的双向路径。
接下来Q行,每行三个数v x k,表示一组询问。

Output

对于每组询问,输出一个整数表示答案。

Sample Input

10 11 4

1 2 3 4 5 6 7 8 9 10

1 4 4

2 5 3

9 8 2

7 8 10

7 1 4

6 7 1

6 4 8

2 1 5

10 8 10

3 4 7

3 4 6

1 5 2

1 5 6

1 5 8

8 9 2

Sample Output

6

1

-1

8

HINT

【数据范围】

N<=10^5, M,Q<=5*10^5,h_i,c,x<=10^9。

不难想但是写起来细节超多

首先建成n棵平衡树,把询问和边都排序

然后每次用边权小于当前询问的边来合并平衡树,已经在同一集合的不理他就行了,所以还要并查集

ps:平衡树的启发式合并就是每次合并两棵树的时候把小的那棵的元素一个一个扔进大的那棵,每次nlogn。这样最坏情况是两棵树一样大,也就是说这样的状态只有logn个,所以复杂度nlog^2n

询问第k大不是随便打

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
#include<deque>
#include<set>
#include<map>
#include<ctime>
#define LL long long
#define inf 0x7ffffff
#define pa pair<int,int>
#define pi 3.1415926535897932384626433832795028841971
using namespace std;
struct query{int v,k,x,rnk;}q[500010];bool operator <(const query &a,const query &b){return a.x<b.x;}
struct edge{int x,y,z;}ed[500010];bool operator <(const edge &a,const edge &b){return a.z<b.z;}
struct SBT{int l,r,son,rnd,rep,dat;}tree[2000010];
int N,M,Q,treesize;
int root[500010];
int ans[500010];
int fa[500010];
inline LL read()
{
LL x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
inline int getfa(int x)
{return fa[x]==x?x:fa[x]=getfa(fa[x]);}
inline void update(int k){tree[k].son=tree[tree[k].l].son+tree[tree[k].r].son+tree[k].rep;}
inline void right_rotate(int &k)
{
int t=tree[k].l;
tree[k].l=tree[t].r;
tree[t].r=k;
tree[t].son=tree[k].son;
update(k);
k=t;
}
inline void left_rotate(int &k)
{
int t=tree[k].r;
tree[k].r=tree[t].l;
tree[t].l=k;
tree[t].son=tree[k].son;
update(k);
k=t;
}
inline void insert(int &k,int x,int rep)
{
if (!k)
{
k=++treesize;
tree[k].dat=x;
tree[k].son=rep;
tree[k].rep=rep;
tree[k].rnd=rand();
return;
}
tree[k].son+=rep;
if (x==tree[k].dat)
{
tree[k].rep+=rep;
return;
}
if (x<tree[k].dat)
{
insert(tree[k].l,x,rep);
if (tree[tree[k].l].rnd>tree[k].rnd)right_rotate(k);
}else
if (x>tree[k].dat)
{
insert(tree[k].r,x,rep);
if (tree[tree[k].r].rnd>tree[k].rnd)left_rotate(k);
}
}
inline int ask(int now,int x)
{
if(now==0)return -1;
if(x<=tree[tree[now].l].son)return ask(tree[now].l,x);
else if(x>tree[tree[now].l].son+tree[now].rep)return ask(tree[now].r,x-tree[tree[now].l].son-tree[now].rep);
else return tree[now].dat;
}
inline void dfs(int from,int &to)
{
if (!from)return;
insert(to,tree[from].dat,tree[from].rep);
dfs(tree[from].l,to);
dfs(tree[from].r,to);
}
inline void merge(int k)
{
int l=getfa(ed[k].x),r=getfa(ed[k].y);
if (l==r)return;
if (tree[root[l]].son<tree[root[r]].son)
{
dfs(root[l],root[r]);
fa[l]=r;
}else
{
dfs(root[r],root[l]);
fa[r]=l;
}
}
inline void init()
{
N=read();M=read();Q=read();
for (int i=1;i<=N;i++)fa[i]=i;
for (int i=1;i<=N;i++)insert(root[i],read(),1);
for (int i=1;i<=M;i++)
{
ed[i].x=read();
ed[i].y=read();
ed[i].z=read();
}
for (int i=1;i<=Q;i++)
{
q[i].v=read();
q[i].x=read();
q[i].k=read();
q[i].rnk=i;
}
sort(ed+1,ed+M+1);
sort(q+1,q+Q+1);
}
inline void work()
{
int now=1;
for(int i=1;i<=Q;i++)
{
while (now<=M&&ed[now].z<=q[i].x)merge(now),now++;
int st=getfa(q[i].v),tot=tree[root[st]].son;
if (tot<q[i].k)ans[q[i].rnk]=-1;
else ans[q[i].rnk]=ask(root[st],tot-q[i].k+1);
}
for (int i=1;i<=Q;i++)
printf("%d\n",ans[i]);
}
int main()
{
init();
work();
return 0;
}


bzoj3545
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: