社区讨论

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 条回复,欢迎继续交流。

正在加载回复...