社区讨论
0pts求调,改为枚举森林后无法过样例
P7834[ONTAK2010] Peaks 加强版参与者 1已保存回复 0
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @lqv082ke
- 此快照首次捕获于
- 2024/01/01 22:16 2 年前
- 此快照最后确认于
- 2024/01/02 15:20 2 年前
rt
CPP#include <bits/stdc++.h>
#define maxn 200005
#define maxm 300005
#define int long long
using namespace std;
/*
个人思路:
先Kruskal建树并求出 dfs 序
之后建主席树
每次查询区间第k大
*/
struct EDGE{
int nxt, to, w;
}e[maxn << 1];
int head[maxn], Cnt;
inline void add(int a,int b){e[++Cnt].nxt = head[a], e[Cnt].to = b, head[a] = Cnt;}
int n, m, q;
//-------dfs处理深度和dfs序,以及fa数组--------------
int f[maxn << 1][32], st[maxn << 1], en[maxn << 1], ma[maxn << 1], siz[maxn << 1], val[maxn], d[maxn], tim, num;
inline void dfs(int u,int father){
f[u][0] = father, st[u] = ++tim, ma[tim] = u; //dfs序
for(int i = 1; i <= 25; i++) f[u][i] = f[f[u][i - 1]][i - 1];
for(int i = head[u]; i; i = e[i].nxt) if(e[i].to != father) dfs(e[i].to, u), siz[u] += siz[e[i].to];
if(!siz[u]) siz[u] = 1;
en[u] = tim;
}
inline int search(int x, int Val){
for(int i = 25; i >= 0; i--) if(f[x][i] && val[f[x][i]] <= Val) x = f[x][i]; //最后一个
return x; //返回根节点
}
//------------------权值线段树查询区间第k小--------------
struct node{
int l, r;
int sum;
};
int rt[maxn << 1];
struct PresidentTree{
node tr[maxn << 6];
int cnt;
#define ls(x) tr[x].l
#define rs(x) tr[x].r
inline void build(int &p, int l, int r){
p = ++cnt;
if(l == r) return;
int mid = (l + r) >> 1;
build(ls(p), l, mid);
build(rs(p), mid + 1, r);
}
inline int change(int rt, int l, int r, int x){
int p = ++cnt;
ls(p) = ls(rt), rs(p) = rs(rt), tr[p].sum = tr[rt].sum + 1;
if(l == r) return p;
int mid = (l + r) >> 1;
if(x <= mid) ls(p) = change(ls(p), l, mid, x);
else rs(p) = change(rs(p), mid + 1, r, x);
return p;
}
inline int query(int x, int y, int l, int r, int k){
int sum = tr[rs(y)].sum - tr[rs(x)].sum;
if(l == r) return l;
int mid = (l + r) >> 1;
if(k <= sum) return query(rs(x), rs(y), mid + 1, r, k);
else return query(ls(x), ls(y), l, mid, k - sum);
}
}tr;
int fa[maxn << 1];
inline int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);}
struct edge{
int from, to, w;
bool operator < (const edge &b) const{
return w < b.w; //边权排序
}
}E[maxm];
inline void Kruskal(){ //重构树
for(int i = 1; i <= maxn - 1; i++) fa[i] = i; //初始化
sort(E + 1, E + 1 + m); //排序
num = n;
int ind[maxn] = {0};
for(int i = 1; i <= m; i++){
int u = find(E[i].from), v = find(E[i].to); //父节点
if(u != v){
num++;
fa[u] = fa[v] = fa[num] = num; //修改
d[num]++;
add(num, u), add(num, v); //建边
val[num] = E[i].w; //权值
}
}
for(int i = n + 1; i <= num; i++) if(d[i] == 0) dfs(i, 0);
}
int tmp[maxn];
signed main(){
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m >> q;
for(int i = 1; i <= n; i++) cin >> d[i], tmp[i] = d[i];
//-----------离散化-----------
sort(tmp + 1, tmp + 1 + n);
int sum = unique(tmp + 1, tmp + 1 + n) - tmp - 1;
for(int i = 1; i <= n; i++) d[i] = lower_bound(tmp + 1, tmp + 1 + sum, d[i]) - tmp;
//-----------Kruskal重构树--------
for(int i = 1; i <= m; i++) cin >> E[i].from >> E[i].to >> E[i].w;
Kruskal(); //建树
//插入主席树
for(int i = 1; i <= num; i++){
rt[i] = rt[i - 1];
if(ma[i] <= n) rt[i] = tr.change(rt[i - 1], 1, sum, d[ma[i]]);
}
int u, x, k, lasans = 0;
//开始读入问题
while(q--){
cin >> u >> x >> k;
u = (u ^ lasans) % n + 1, k = (k ^ lasans) % n + 1, x = x ^ lasans;
for(int i = 25; ~i; i--) if(f[u][i] && val[f[u][i]] <= x) u = f[u][i];
if(siz[u] < k){
cout << "-1" << '\n';
lasans = 0;
continue;
}
cout << (lasans = tmp[tr.query(rt[st[u] - 1], rt[en[u]], 1, sum, k)]) <<'\n';
}
return 0;
}
回复
共 0 条回复,欢迎继续交流。
正在加载回复...