社区讨论
求调主席树样例过了但全 WA
P3241[HNOI2015] 开店参与者 2已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @m0d7nmqn
- 此快照首次捕获于
- 2024/08/28 10:02 2 年前
- 此快照最后确认于
- 2025/11/04 22:13 4 个月前
做法是树剖+主席树(下标是 dfn)
每个点的权值是它到父亲的边权,对于按年龄排序后每个点 依次插入 路径上的所有点,查询时在排好序的年龄中二分出的 对应的位置,然后答案是 。询问查询 路径上的权值,这样能查出来年龄在 之间的点和 的 LCA 的 之和,利用 得出
空间我不太会算,但是按严格 算的话肯定爆掉,看 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 条回复,欢迎继续交流。
正在加载回复...