社区讨论

求调主席树样例过了但全 WA

P3241[HNOI2015] 开店参与者 2已保存回复 2

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
2 条
当前快照
1 份
快照标识符
@m0d7nmqn
此快照首次捕获于
2024/08/28 10:02
2 年前
此快照最后确认于
2025/11/04 22:13
4 个月前
查看原帖
做法是树剖+主席树(下标是 dfn)
每个点的权值是它到父亲的边权,对于按年龄排序后每个点 xx 依次插入 1x1 \sim x 路径上的所有点,查询时在排好序的年龄中二分出的 l,rl, r 对应的位置,然后答案是 [1,r][1,l1][1, r] - [1, l - 1]。询问查询 uu 路径上的权值,这样能查出来年龄在 [l,r][l, r] 之间的点和 uu 的 LCA 的 disdis 之和,利用 dist(u,v)=dis[u]+dis[v]2×dis[LCA(u,v)]dist(u, v) = dis[u] + dis[v] - 2\times dis[\text{LCA}(u, v)] 得出 x=lrdis(u,x)\sum \limits_{x = l}^rdis(u, x)
空间我不太会算,但是按严格 2nlog22n2n \log_2^2n 算的话肯定爆掉,看 WA 后显示的内存占用感觉应该不是爆空间的问题
CPP
#include<bits/stdc++.h>
using namespace std;
#define CIO
#ifdef LOCAL
ifstream in("data.in"); ostream &out = cout; ofstream err;
#endif
#ifdef CIO
istream &in = cin; ostream &out = cout;
#endif
#define newl '\n'

using LL = long long;
const int N = 150005;
int n, q, A, age[N], order[N];
int head[N], nxt[2 * N], to[2 * N], val[2 * N], tot;
void add(int x, int y, int z){
    to[++tot] = y, val[tot] = z, nxt[tot] = head[x], head[x] = tot;
}
int dfn[N], ts, siz[N], son[N], fr[N], fa[N], top[N], sum[N], dis[N];
LL sdis[N];
void upd_inf(int x){
    siz[x] = 1;
    for(int e = head[x]; e; e = nxt[e]){
        int y = to[e];
        if(y == fa[x]) continue;
        fa[y] = x, fr[y] = e;
        dis[y] = dis[x] + val[e];
        upd_inf(y), siz[x] += siz[y];
        if(siz[y] > siz[son[x]]) son[x] = y;
    }
}
void mark(int x, int tp){
    dfn[x] = ++ts, top[x] = tp;
    if(son[x]) mark(son[x], tp);
    for(int e = head[x]; e; e = nxt[e]){
        int y = to[e];
        if(y == son[x] || y == fa[x]) continue;
        mark(y, y);
    }
}
struct node{
    int ls, rs, ver, tag; LL sum;
} tr[47476266]; int rt[N], t;
void update(int &p){
    if(!p) p = ++t, tr[p].ver = ts;
    else if(tr[p].ver < ts){
        tr[++t] = tr[p];
        tr[p = t].ver = ts;
    }       
}
int cap(int l1, int r1, int l2, int r2){
    return sum[min(r1, r2)] - sum[max(l1, l2) - 1];
}
void modify(int ql, int qr, int &p, int l, int r){
    update(p);
    tr[p].sum += cap(l, r, ql, qr);
    if(ql <= l && r <= qr){
        tr[p].tag++;
        return;
    }
    int mid = (l + r) >> 1;
    if(ql <= mid) modify(ql, qr, tr[p].ls, l, mid);
    if(mid < qr) modify(ql, qr, tr[p].rs, mid + 1, r);
}
LL query(int ql, int qr, int p, int l, int r){
    if(ql <= l && r <= qr) return tr[p].sum;
    int mid = (l + r) >> 1;
    LL res = 1LL * cap(l, r, ql, qr) * tr[p].tag;
    if(ql <= mid) res += query(ql, qr, tr[p].ls, l, mid);
    if(mid < qr) res += query(ql, qr, tr[p].rs, mid + 1, r);
    return res;
}
LL solve(int x, int y){
    LL res = 0;
    while(x){
        res += query(dfn[top[x]], dfn[x], rt[y], 1, n);
        x = fa[top[x]];
    }
    return res;
}
int get_last(LL v){
    int l = 0, r = n;
    while(l < r){
        int mid = (l + r + 1) >> 1;
        if(age[order[mid]] <= v) l = mid;
        else r = mid - 1;
    }
    return l;
}

int main(){
    ios::sync_with_stdio(0), in.tie(0), out.tie(0);
    in >> n >> q >> A;
    for(int i = 1; i <= n; i++) in >> age[i];
    for(int i = 1; i <= n; i++) order[i] = i;
    sort(order + 1, order + n, [](const int &x, const int &y){
        return age[x] < age[y];
    });
    for(int i = 1; i < n; i++){
        int u, v, w; in >> u >> v >> w;
        add(u, v, w), add(v, u, w);
    }
    upd_inf(1), mark(1, 1), ts = 0;
    for(int i = 1; i <= n; i++) sum[dfn[i]] = val[fr[i]];
    for(int i = 1; i <= n; i++) sum[i] += sum[i - 1];
    for(int i = 1; i <= n; i++) sdis[i] = sdis[i - 1] + dis[order[i]];
    for(int i = 1; i <= n; i++){
        int x = order[i]; ++ts, rt[i] = rt[i - 1];
        while(x){
            modify(dfn[top[x]], dfn[x], rt[i], 1, n);
            x = fa[top[x]];
        }
    }
    LL ans = 0;
    while(q--){
        int x, a, b; in >> x >> a >> b;
        int l = min((a + ans) % A, (b + ans) % A);
        int r = max((a + ans) % A, (b + ans) % A);
        l = get_last(l - 1), r = get_last(r);
        ans = -2 * (solve(x, r) - solve(x, l)) + sdis[r] - sdis[l] + LL(r - l) * dis[x];
        out << ans << newl;
    }
    return 0;
}

回复

2 条回复,欢迎继续交流。

正在加载回复...