P4315 月下“毛景树”
月下“毛景坑”,调试了几个小时,终于过了
线段树,真的牛(永远的坑)
坑很多,都是些注意点,希望同样踩坑的朋友能在这里找到答案
注意点
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
//存图
int cnt,h[N], to[N*2], w[N*2], ne[N*2];
void add(int a, int b, int c) {
to[++cnt] = b;
w[cnt] = c;
ne[cnt] = h[a];
h[a] = cnt;
}
//树链
int dep[N], sz[N], son[N], fa[N],a[N];
void dfs1(int u, int father) {
fa[u] = father; dep[u] = dep[father] + 1;
sz[u] = 1;
for (int i = h[u]; i; i = ne[i]) {
int v = to[i];
if (v == father) continue;
a[v] = w[i];
dfs1(v, u);
sz[u] += sz[v];
if (sz[son[u]] < sz[v]) son[u] = v;
}
}
int top[N], id[N], tt, nw[N];
void dfs2(int u, int t) {
top[u] = t; id[u] = ++tt; nw[tt] = a[u];
if (!son[u])return;
dfs2(son[u], t);
for (int i = h[u]; i; i = ne[i]) {
int v = to[i];
if (v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
//线段树
#define lc k<<1
#define rc k<<1|1
struct tree {
int l, r;
int sum, lz;
int cov;
}tr[4*N];
void pushup(int k) {
tr[k].sum = max(tr[lc].sum , tr[rc].sum);//注意求最大
}
void pushdown(int k) {
if (~tr[k].cov) {
tr[lc].sum = tr[k].cov;//求最大,直接赋值就好
tr[rc].sum = tr[k].cov;
tr[lc].cov = tr[k].cov;
tr[rc].lz=tr[lc].lz = 0;//注意改为0
tr[rc].cov = tr[k].cov;
tr[k].cov = -1;//注意修改
}
if (tr[k].lz) {
tr[lc].sum += tr[k].lz;
tr[rc].sum += tr[k].lz;
tr[lc].lz += tr[k].lz;
tr[rc].lz += tr[k].lz;
tr[k].lz=0;
}
}
//建树
void build(int k, int l, int r) {
tr[k] = { l,r ,0,0,-1};
if (l == r) {
tr[k].sum = nw[l];
return;
}
int mid = l + r >> 1;
build(lc, l, mid); build(rc, mid + 1, r);
pushup(k);
}
//区间查询
int query(int k, int l, int r) {
if (tr[k].l >= l && tr[k].r <= r) return tr[k].sum;
pushdown(k);
int ans = 0;
int mid = tr[k].l + tr[k].r >> 1;
if (l <= mid) ans =max( query(lc, l, r),ans);
if (r > mid) ans =max( query(rc, l, r),ans);
return ans;
}
int query_path(int u, int v) {
int ans = 0;
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
ans = max(query(1, id[top[u]], id[u]),ans);
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
ans =max( query(1, id[v]+1, id[u]),ans);
return ans;
}
//区间加
void modify_add(int k, int l, int r,int z) {
if (tr[k].l >= l && tr[k].r <= r) {
tr[k].sum += z;
tr[k].lz += z;
return;
}
pushdown(k);
int mid = tr[k].l + tr[k].r >> 1;
if (l <= mid) modify_add(lc, l, r,z);
if (r > mid) modify_add(rc, l, r,z);
pushup(k);
}
void Add(int u, int v, int z) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
modify_add(1, id[top[u]], id[u],z);
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
modify_add(1, id[v]+1, id[u],z);//注意id[v]+1,选它的儿子
}
//单点修改
void change(int k, int x, int z) {
if (tr[k].l == x && tr[k].r == x) {
tr[k].sum =z;
return;
}
pushdown(k);
int mid = tr[k].l + tr[k].r >> 1;
if (x <= mid) change(lc, x,z);
else if (x > mid) change(rc, x,z);
pushup(k);
}
//区间覆盖
void modify_cov(int k, int l, int r, int z) {
if (tr[k].l >= l && tr[k].r <= r) {
tr[k].cov = z;
tr[k].sum = z;
tr[k].lz = 0;//注意,要改为0
return;
}
pushdown(k);
int mid = tr[k].l + tr[k].r >> 1;
if (l <= mid) modify_cov(lc, l, r, z);
if (r > mid) modify_cov(rc, l, r, z);
pushup(k);
}
void Cover(int u, int v, int z) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) swap(u, v);
modify_cov(1, id[top[u]], id[u], z);
u = fa[top[u]];
}
if (dep[u] < dep[v]) swap(u, v);
modify_cov(1, id[v]+1, id[u], z);
}
int main() {
int n;
cin >> n;
for (int i = 1; i < n; i++) {
int x, y,z;
cin >> x >> y>>z;
add(x, y, z);
add(y, x, z);
}
dfs1(1, 0);
dfs2(1, 1);
build(1, 1, n);
string s;
while (cin >> s) {
if (s == "Stop") break;
if (s == "Max") {
int x, y;
cin >> x >> y;
cout << query_path(x,y) << '\n';
}
else if(s=="Cover") {
int x, y, z;
cin >> x >> y >> z;
Cover(x, y,z);
}
else if (s == "Add") {
int x, y, z;
cin >> x >> y >> z;
Add(x, y, z);
}
else {
int x, z;
cin >> x >> z;
x = dep[to[x << 1]] < dep[to[x*2 - 1]] ? to[x *2 - 1] : to[x << 1];//深度更深的为要改的点
change(1,id[x], z);
}
}
return 0;
}