CultReborn @ 2023-11-15 11:24:41
WA 0pts
#include<bits/stdc++.h>
#define LL long long
using namespace std;
const int maxn = 100005;
inline LL Read();void Rite(LL x);
int a[maxn],c[maxn],n;
int head[maxn],cnt(-1);
int fth[maxn],dep[maxn],dfn[maxn];
int siz[maxn],son[maxn],top[maxn];
int ti = 0;
struct node{
int u,to,nxt,cst;
}edge[maxn * 2];
struct SegmentTree{
int left,right;
LL data;
#define l(p) t[p].left
#define r(p) t[p].right
#define d(p) t[p].data
}t[maxn * 4];
void Input(int u,int v,int w){
edge[++cnt] = {u,v,head[u],w};
head[u] = cnt;
}
void DFS1(int u,int fa){
dep[u] = dep[fa] + 1;
siz[u] = 1;
fth[u] = fa;
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(v == fa) continue;
c[v] = edge[i].cst;
DFS1(v,u);
siz[u] += siz[v];
if(!son[u] || siz[son[u]] < siz[v])
son[u] = v;
}
}
void DFS2(int u,int tp){
dfn[u] = ++ti;
a[ti] = c[u];
top[u] = tp;
if(!son[u]) return;
DFS2(son[u],tp);
for(int i = head[u];~i;i = edge[i].nxt){
int v = edge[i].to;
if(son[u] != v && fth[u] != v)
DFS2(v,v);
}
}
void Build(int p,int l,int r){
l(p) = l; r(p) = r;
if(l == r){d(p) = a[l];return;}
int mid = (l + r) / 2;
Build(p * 2,l,mid);
Build(p*2+1,mid + 1,r);
d(p) = max(d(p * 2),d(p*2+1));
}
void Change(int p,int l,LL d){
if(l(p) == r(p)){d(p) = max(d,d(p));return;}
int mid = (l(p) + r(p)) / 2;
if(l <= mid) Change(p * 2,l,d);
else Change(p*2+1,l,d);
d(p) = max(d(p * 2),d(p*2+1));
}
LL Ask(int p,int l,int r){
if(l <= l(p) && r >= r(p))
return d(p);
LL ans(INT_MIN);
int mid = (l(p) + r(p)) / 2;
if(l <= mid) ans = max(ans,Ask(p * 2,l,r));
if(r > mid) ans = max(ans,Ask(p*2+1,l,r));
return ans;
}
LL Query(int u,int v){
if(u == v) return 0;
LL ans(0);
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
ans = max(ans,Ask(1,dfn[top[u]],dfn[u]));
u = fth[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
ans = max(ans,Ask(1,dfn[u] + 1,dfn[v]));
return ans;
}
int main(){
n = Read();
memset(head,-1,sizeof(head));
for(int i = 1;i <= n - 1;++i){
int u(Read()),v(Read()),w(Read());
Input(u,v,w); Input(v,u,w);
}
DFS1(1,0); DFS2(1,1); Build(1,1,n);
while(1){
string s; cin >> s;
if(s[0] == 'D') break;
int x(Read()),y(Read());
if(s[0] == 'C'){
x = (x - 1) * 2;
int u(edge[x].u),v(edge[x].to);
if(fth[v] == u) swap(u,v);
Change(1,dfn[u],y);
}
else Rite(Query(x,y)),putchar('\n');
}
return 0;
}
inline LL Read(){
char c = getchar();
LL x = 0,f = 1;
while(c < '0' || c > '9'){
if(c == '-') f = -1;
c = getchar();
}
while(c >= '0' && c <= '9'){
x = x * 10 + c - '0';
c = getchar();
}
return x * f;
}void Rite(LL x){
if(x < 0) putchar('-'),x = -x;
if(x > 9) Rite(x / 10);
putchar(x % 10 + '0');
}
by ATZdhjeb @ 2023-11-15 11:35:34
hack:
5
1 2 1
1 4 1
2 3 1
4 5 1
QUERY 1 5
CHANGE 2 2
QUERY 1 5
DONE
by ATZdhjeb @ 2023-11-15 11:36:20
查询的时候要考虑两个点跳到一起的情况
by CultReborn @ 2023-11-15 12:57:46
@ATZdhjeb 十分感谢,十分感谢
by CultReborn @ 2023-11-15 13:05:43
@ATZdhjeb 但是好像两个点不可能跳到一起啊
by CultReborn @ 2023-11-15 13:07:49
我的代码也输出了
1
2
似乎没有问题
by ATZdhjeb @ 2023-11-15 13:12:23
@CultReborn 啊??
我本地跑你的代码输出两个 1(
by ATZdhjeb @ 2023-11-15 13:15:03
就,从理论上分析,它是把边权传到儿子节点上,然后两个点的 LCA 的值存的是 LCA 到 LCA 父亲的边权,所以不能算进去才对。
然后现在看一下好像我的 hack 也有点问题,等我再想想(
by CultReborn @ 2023-11-15 13:17:18
@ATZdhjeb 78行的
while(top[u] != top[v])
规避了两个点跳到一起的情况,我这边确实是 1 2。
已关注,感谢感谢!
by ATZdhjeb @ 2023-11-15 13:27:51
@CultReborn 好好好,你是线段树修改错了,直接赋值,不是取 max。查询确实没错。
以及为什么最近我一水贴就成小丑,这下发现自己树剖也没学懂了。
by CultReborn @ 2023-11-15 13:37:00
@ATZdhjeb 以及为什么最近我一水贴就小丑,这下发现自己线段树也没学懂了。