题目链接:戳我
woc这题也太毒了吧。。。。卡空间要死啊???
说一说怎么做——因为本题强制在线,所以用kruskal重构树,开始将边权从小到大排序,这样的话用最后一个新建的节点为根之后就是一个大根堆,所有边权小的都在节点的子树里。求K大——主席树。不过因为我们维护的是一棵树而不是序列,所以还要先dfs序一下。
可惜蒟蒻码力不够,虽然看出来了怎么写但是还是不断锅锅锅,最后还是去参照了大佬的题解才过的这个题。。。。。
bzoj上题面不是特别清楚。在这里补充一下——
v=v xor lastans,x=x xor lastans,k=k xor lastans。如果lastans=-1则不变。
这句话的意思是lastans是上一次询问的答案,如果上一次ans==-1,就不对v,x,k进行异或操作。开始lastans=0。
然后题目让求的是第K大而非第K小(因为中国汉字意义博大精深,我看到第几大总是习惯性的先从小的想。。。。。告辞
补一下正确的样例输入输出:
输入:
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
输出:
6
10
9
-1
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#define MAXN 200100
using namespace std;
int n,m,tot,edge_number,cnt,tt,num,lastans,q,kkk;
int pre[MAXN],h[MAXN],head[MAXN],fa[MAXN],dis[MAXN];
int ini[MAXN],rt[MAXN],dfn[MAXN],low[MAXN],f[MAXN][20];
struct Edge{int nxt,to;}edge[MAXN<<1];
struct Edge2{int u,v,w;}e[MAXN<<2];
struct Node{int ls,rs,v;}t[MAXN<<5];
inline void add(int from,int to)
{
edge[++edge_number].nxt=head[from];
edge[edge_number].to=to;
head[from]=edge_number;
}
inline int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
inline bool cmp(struct Edge2 x,struct Edge2 y){return x.w<y.w;}
inline void dfs(int now,int ff)
{
//printf("now=%d ff=%d
",now,ff);
if(now<=n) dfn[now]=low[now]=++tt,ini[tt]=now;
else dfn[now]=(int)1e9,low[now]=0;
f[now][0]=ff;
for(int i=1;i<=19;i++)
f[now][i]=f[f[now][i-1]][i-1];
for(int i=head[now];i;i=edge[i].nxt)
{
dfs(edge[i].to,now);
dfn[now]=min(dfn[now],dfn[edge[i].to]);
low[now]=max(low[now],low[edge[i].to]);
}
}
inline void modify(int &now,int ff,int l,int r,int pos)
{
now=++kkk;
t[now]=t[ff],t[now].v++;
//printf("now=%d ff=%d l=%d r=%d pos=%d
",now,ff,l,r,pos);
if(l==r) return;
int mid=(l+r)>>1;
if(pos<=mid) modify(t[now].ls,t[ff].ls,l,mid,pos);
else modify(t[now].rs,t[ff].rs,mid+1,r,pos);
}
inline int query(int now,int ff,int l,int r,int k)
{
if(l==r) return pre[l];
int mid=(l+r)>>1;
int cur_ans=t[t[ff].rs].v-t[t[now].rs].v;
if(cur_ans>=k) query(t[now].rs,t[ff].rs,mid+1,r,k);
else query(t[now].ls,t[ff].ls,l,mid,k-cur_ans);
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
//freopen("ce.out","w",stdout);
#endif
scanf("%d%d%d",&n,&m,&q);
for(int i=1;i<=n;i++)
scanf("%d",&h[i]),pre[i]=h[i];
sort(&pre[1],&pre[1+n]);
cnt=unique(&pre[1],&pre[1+n])-pre-1;
for(int i=1;i<=n;i++)
h[i]=lower_bound(&pre[1],&pre[1+cnt],h[i])-pre;
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
sort(&e[1],&e[1+m],cmp);
tot=n;
for(int i=1;i<=m;i++)
{
int a=find(e[i].u),b=find(e[i].v);
if(a==b) continue;
++tot;
fa[tot]=fa[a]=fa[b]=tot;
dis[tot]=e[i].w;
add(tot,a),add(tot,b);
}
dfs(tot,0);
for(int i=1;i<=n;i++)
modify(rt[i],rt[i-1],1,cnt,h[ini[i]]);
//for(int i=1;i<=n;i++) printf("rt[%d]=%d
",i,rt[i]);
for(int i=1;i<=q;i++)
{
int v,x,k;
scanf("%d%d%d",&v,&x,&k);
if(lastans!=-1) v^=lastans,x^=lastans,k^=lastans;
for(int i=19;i>=0;i--)
if(f[v][i]&&dis[f[v][i]]<=x)
v=f[v][i];
//printf("%d %d
",rt[dfn[v]-1],rt[low[v]]);
if(low[v]-dfn[v]+1<k) lastans=-1;
else lastans=query(rt[dfn[v]-1],rt[low[v]],1,cnt,k);
printf("%d
",lastans);
}
return 0;
}
不过有个问题是 从BZOJ上捞下来的数据为什么我自己在lemon上测是RE+TLE 放到BZOJ上竟然又跑过了????
update:没开栈。。开了就过了