Peaks
Posted fhq_treap
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Peaks相关的知识,希望对你有一定的参考价值。
很好我心态崩了。
————————————————
这里给出两种做法,代码上都有一些问题,建议不要\\(copy\\).
一:离线做法
考虑直接线段树合并,把问题按边权排。
做完了。
离线做法
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll long long
#define M 2000003
#define N 100003
ll head[N];
ll n,m;
ll v[M],ls[M],rs[M],fa[N],cnt,t[M];
inline void up(ll now){v[now] = v[ls[now]] + v[rs[now]];}
inline ll get(ll now){return now == fa[now] ? now : fa[now] = get(fa[now]);}
#define mid ((l + r) >> 1)
ll tag;
inline int build(int l,int r,int to){
int now = ++cnt;
// std::cout<<now<<" "<<l<<" "<<r<<std::endl;
if(l == r){
t[now] = tag;
v[now] = 1;
return now;
}
if(to <= mid)
ls[now] = build(l,mid,to);
else
rs[now] = build(mid + 1,r,to);
up(now);
return now;
}
inline int merge(ll a,ll b,ll l,ll r){
// std::cout<<a<<" "<<b<<" "<<l<<" "<<r<<std::endl;
if(!a || !b)
return a + b;
if(l == r){
v[a] += v[b];
return a;
}
ls[a] = merge(ls[a],ls[b],l,mid);
rs[a] = merge(rs[a],rs[b],mid + 1,r);
up(a);
return a;
}
inline int Q(ll now,ll q,ll l,ll r){
// std::cout<<now<<" "<<q<<" "<<l<<" "<<r<<" "<<v[now]<<" "<<std::endl;
if(l == 1 && r == n && q > v[now])
return -1;
if(l == r)
return t[now];
if(v[rs[now]] >= q)
return Q(rs[now],q,mid + 1,r);
else
return Q(ls[now],q - v[rs[now]],l,mid);
}
inline void dfs(ll now,ll l,ll r){
if(now){
// std::cout<<now<<" "<<l<<" "<<r<<" "<<v[now]<<std::endl;
dfs(ls[now],l,mid);
dfs(rs[now],mid + 1,r);
}
}
struct P{int to,s,v;}e[N << 4];
inline bool operator < (P a,P b){return a.v < b.v;}
struct Qp{int v,x,k,id;}Qi[N * 5];
ll ans[N * 5];
inline bool operator < (Qp a,Qp b){return a.x < b.x;}
ll q,num[N],b[N],s;
int main(){
scanf("%lld%lld",&n,&m);
scanf("%lld",&q);
for(int i = 1;i <= n;++i)
fa[i] = i;
for(int i = 1;i <= n;++i)
scanf("%lld",&num[i]),b[++b[0]] = num[i];
std::sort(b + 1,b + n + 1);
s = std::unique(b + 1,b + n + 1) - b - 1;
for(int i = 1;i <= n;++i){
ll x = std::lower_bound(b + 1,b + s + 1,num[i]) - b;
tag = i;
head[i] = build(1,n,x);
}
for(int i = 1;i <= m;++i)
scanf("%d%d%d",&e[i].s,&e[i].to,&e[i].v);
std::sort(e + 1,e + m + 1);
// for(int i = 1;i <= m;++i)
// std::cout<<e[i].s<<" "<<e[i].to<<" "<<e[i].v<<std::endl;
for(int i = 1;i <= q;++i){
Qi[i].id = i;
scanf("%d%d%d",&Qi[i].v,&Qi[i].x,&Qi[i].k);
}
std::sort(Qi + 1,Qi + q + 1);
// for(int i = 1;i <= q;++i)
// std::cout<<Qi[i].v<<" "<<Qi[i].x<<" "<<Qi[i].k<<std::endl;
ll now = 1;
for(int i = 1;i <= q;++i){
// std::cout<<Qi[i].v<<" "<<Qi[i].x<<" "<<Qi[i].k<<std::endl<<std::endl;
while(e[now].v <= Qi[i].x && now <= m){
// std::cout<<e[now].s<<" "<<e[now].to<<" "<<e[now].v<<std::endl;
// std::cout<<now<<std::endl;
ll x = e[now].s,y = e[now].to;
ll fx = get(x),fy = get(y);
if(fx != fy){
// std::cout<<fx<<" "<<fy<<" "<<head[fx]<<" "<<head[fy]<<std::endl;
fa[fx] = fy;
head[fy] = merge(head[fx],head[fy],1,n);
}
++now;
}
// puts("");
ll fx = get(Qi[i].v);
// std::cout<<Q(head[fx],Qi[i].k,1,n)<<std::endl;
ll an = Q(head[fx],Qi[i].k,1,n);
if(an != -1)
ans[Qi[i].id] = num[an];
else
ans[Qi[i].id] = -1;
}
for(int i = 1;i <= q;++i)
std::cout<<ans[i]<<std::endl;
}
二:在线做法
考虑重构树,那么在一个权值为\\(k\\)的方点下的原点均可以小于等于\\(k\\)的边走到。
倍增+主席树做完了。
(莫名\\(RE\\)心态没了)
在线做法
#include<iostream>
#include<cstdio>
#include<algorithm>
#define ll int
#define N 200005
ll n,m,q,num[N],b[N];
struct Map{int to,s,v;}e[N];
inline bool operator < (Map a,Map b){return a.v < b.v;}
//________________________//map
ll head[N << 1],v[N << 2],cnt;
struct T{int to,next;}t[N * 6];
inline void add(int x,int y){
// std::cout<<x<<" "<<y<<std::endl;
t[++cnt].to = y;
t[cnt].next = head[x];
head[x] = cnt;
}
ll l[N << 1],r[N << 1],tnum[N],dfncnt,fi[N << 1][25];
inline void dfs(int u,int f){
if(u == 0 || u == f)
return ;
// std::cout<<u<<" "<<v[u]<<std::endl;
fi[u][0] = f;
for(int i = 1;i <= 19;++i)
fi[u][i] = fi[fi[u][i - 1]][i - 1];
l[u] = dfncnt;
if(head[u] == 0){
tnum[++dfncnt] = std::lower_bound(b + 1,b + b[0] + 1,num[u]) - b;
r[u] = dfncnt;
return ;
}
for(int i = head[u];i;i = t[i].next){
int v = t[i].to;
if(v == f)
continue;
dfs(v,u);
}
r[u] = dfncnt;
}
//________________________//tree
ll fa[N];
inline ll find(int x){return (x == fa[x]) ? x : fa[x] = find(fa[x]);}
//________________________//dsu
int tcnt;
int thead[N];
#define mid ((l + r) >> 1)
struct Seg{int l,r,s;Seg(){l = r = s = 0;};}Tr[N * 40];
#define l(x) Tr[x].l
#define r(x) Tr[x].r
#define v(x) Tr[x].s
//tnum[M]
inline void change(int &now,int pre,int l,int r,int to){
if(!now)now = ++ tcnt ;
// std::cout<<now<<" "<<pre<<" "<<l<<" "<<r<<" "<<to<<std::endl;
v(now) = v(pre) + 1;
if(l == r)return;
if(to > mid){l(now) = l(pre),change(r(now),r(pre),mid + 1,r,to);}
else{r(now) = r(pre),change(l(now),l(pre),l,mid,to);}
}
inline void build(){
for(int i = 1;i <= n;++i)
change(thead[i],thead[i - 1],1,n,tnum[i]);
}
inline ll grt(int u,ll x){
for(int i = 19;i >= 0;--i){
if(v[fi[u][i]] <= x)
u = fi[u][i];
}
return u;
}
inline ll Q(int lnow,int rnow,int l,int r,int k){
int rk = v(r(rnow)) - v(r(lnow));
// std::cout<<lnow<<" "<<rnow<<" "<<l<<" "<<r<<" "<<k<<std::endl;
if(l == r){
if(k - (v(rnow) - v(lnow)) == 0)
return l;
else
return 0;
}
if(rk >= k)
return Q(r(lnow),r(rnow),mid + 1,r,k);
else
return Q(l(lnow),l(rnow),l,mid,k - rk);
}
//______________________//Seg tree
ll tot;
inline void kruskal(){
ll bcnt = 0;
tot = n;
for(int i = 1;i <= m && bcnt < n - 1;++i){
ll x = e[i].s,y = e[i].to;
ll fx = find(x),fy = find(y);
if(fx != fy){
// std::cout<<e[i].s<<" "<<e[i].to<<" "<<e[i].v<<" "<<fx<<" "<<fy<<std::endl;
v[++tot] = e[i].v;
add(tot,fx);
add(tot,fy);
fa[tot] = fa[fx] = fa[fy] = tot;
bcnt ++ ;
}
}
}
//_______________________//rebuild;
int main(){
// freopen("q.in","r",stdin);
// freopen("q.ans","w",stdout);
scanf("%d%d%d",&n,&m,&q);
for(int i = 1;i <= n;++i)
scanf("%d",&num[i]),b[++b[0]] = num[i];
std::sort(b + 1,b + b[0] + 1);
b[0] = std::unique(b + 1,b + b[0] + 1) - b - 1;
for(int i = 1;i <= m;++i){scanf("%d%d%d",&e[i].s,&e[i].to,&e[i].v);}
std::sort(e + 1,e + m + 1);
for(int i = 1;i <= n;++i)
fa[i] = i;
// puts("");
kruskal();
dfs(find(1),0);
build();
b[0] = -1;
v[0] = 1e9 + 7;
for(int i = 1;i <= q;++i){
ll v,x,k;
scanf("%d%d%d",&v,&x,&k);
ll rt = grt(v,x);
// std::cout<<rt<<std::endl;
std::cout<<b[Q(thead[l[rt]],thead[r[rt]],1,n,k)]<<std::endl;
}
}
/*
7 7 70
11493 8611 10935 23931 3939 16004 14404
3 7 727057
3 2 860811
3 1 739841
3 5 123028
6 1 501761
2 6 119601
3 4 760129
4 372996 1
*/
建议重构树的题目能离线做还是离线做吧,很难调。
以上是关于Peaks的主要内容,如果未能解决你的问题,请参考以下文章
bzoj3545 [ONTAK2010]Peaksbzoj3551 [ONTAK2010]Peaks加强版