题目链接
把一个u上的权为x的矿工和一个v上的权为y的矿工匹配了,相当于u出现了一个权为-x的黄金,v出现了一个权为-y的黄金。
每个点开个set,维护每个轻子树能爬上来的最大权的矿工和自己点上的矿工。当一条重链上的流量发生改变,只有这条链顶节点的父亲的set需要改变,删除原来的最大权矿工,加入现在的能爬上来的最大权矿工。需要树链剖分,在线段树上维护流量和最值。
#include
#include
#include
#include
#include
using namespace std;
const int N=100005,inf=0x7f7f7f7f;
int n,q,u,v,d,op,cnt,head[N],to[N*2],nxt[N*2],dd[N*2];
int idx,fa[N],siz[N],dep[N],dis[N],son[N],dfn[N],pos[N],top[N],bot[N];
long long ans;
pair<int,int> last[N];
void adde(int u,int v,int d){
to[++cnt]=v;
nxt[cnt]=head[u];
dd[cnt]=d;
head[u]=cnt;
}
void dfs(int u){
siz[u]=1;
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=fa[u]){
fa[v]=u;
dep[v]=dep[u]+1;
dis[v]=dis[u]+dd[i];
dfs(v);
siz[u]+=siz[v];
if(!son[u]||siz[son[u]]<siz[v]){
son[u]=v;
}
}
}
}
void dfs(int u,int tp){
dfn[u]=++idx;
pos[idx]=u;
top[u]=tp;
if(son[u]){
dfs(son[u],tp);
bot[u]=bot[son[u]];
}else{
last[tp]=make_pair(-inf,0);
bot[u]=u;
}
int v;
for(int i=head[u];i;i=nxt[i]){
v=to[i];
if(v!=fa[u]&&v!=son[u]){
dfs(v,v);
}
}
}
struct tree1{
int minn[N*4],tag[N*4];
void pushdown(int o){
if(tag[o]){
tag[o*2]+=tag[o];
minn[o*2]+=tag[o];
tag[o*2+1]+=tag[o];
minn[o*2+1]+=tag[o];
tag[o]=0;
}
}
void update(int o,int l,int r,int L,int R,int v){
if(L<=l&&R>=r){
tag[o]+=v;
minn[o]+=v;
return;
}
pushdown(o);
int mid=(l+r)/2;
if(L<=mid){
update(o*2,l,mid,L,R,v);
}
if(R>mid){
update(o*2+1,mid+1,r,L,R,v);
}
minn[o]=min(minn[o*2],minn[o*2+1]);
}
int queryl(int o,int l,int r,int L,int R){
if(L>R||minn[o]>0){
return -1;
}
int mid=(l+r)/2;
if(L<=l&&R>=r){
if(l==r){
return l;
}
pushdown(o);
int res=queryl(o*2,l,mid,L,R);
if(res==-1){
res=queryl(o*2+1,mid+1,r,L,R);
}
return res;
}
pushdown(o);
int res=-1;
if(L<=mid){
res=queryl(o*2,l,mid,L,R);
}
if(R>mid&&res==-1){
res=queryl(o*2+1,mid+1,r,L,R);
}
return res;
}
int queryr(int o,int l,int r,int L,int R){
if(L>R||minn[o]>0){
return -1;
}
int mid=(l+r)/2;
if(L<=l&&R>=r){
if(l==r){
return l;
}
pushdown(o);
int res=queryr(o*2+1,mid+1,r,L,R);
if(res==-1){
res=queryr(o*2,l,mid,L,R);
}
return res;
}
pushdown(o);
int res=-1;
if(R>mid){
res=queryr(o*2+1,mid+1,r,L,R);
}
if(L<=mid&&res==-1){
res=queryr(o*2,l,mid,L,R);
}
return res;
}
}t1;
struct tree2{
pair<int,int> maxn[N*4];
set<pair<int,int> > st[N*4];
void build(int o,int l,int r){
if(l==r){
maxn[o]=make_pair(-inf,0);
return;
}
int mid=(l+r)/2;
build(o*2,l,mid);
build(o*2+1,mid+1,r);
maxn[o]=max(maxn[o*2],maxn[o*2+1]);
}
void update(int o,int l,int r,int k,pair<int,int> pv,pair<int,int> v){
if(l==r){
if(pv.first!=-inf){
st[o].erase(pv);
}
if(v.first!=-inf){
st[o].insert(v);
}
if(st[o].empty()){
maxn[o]=make_pair(-inf,pos[l]);
}else{
maxn[o]=*st[o].rbegin();
}
return;
}
int mid=(l+r)/2;
if(k<=mid){
update(o*2,l,mid,k,pv,v);
}else{
update(o*2+1,mid+1,r,k,pv,v);
}
maxn[o]=max(maxn[o*2],maxn[o*2+1]);
}
pair<int,int> query(int o,int l,int r,int L,int R){
if(L==l&&R==r){
return maxn[o];
}
int mid=(l+r)/2;
if(R<=mid){
return query(o*2,l,mid,L,R);
}else if(L>mid){
return query(o*2+1,mid+1,r,L,R);
}else{
return max(query(o*2,l,mid,L,mid),query(o*2+1,mid+1,r,mid+1,R));
}
}
}t2,t3;
void add(int u,int v,int d){
while(top[u]!=top[v]){
t1.update(1,1,n,dfn[top[u]],dfn[u],d);
u=fa[top[u]];
}
if(u!=v){
t1.update(1,1,n,dfn[v]+1,dfn[u],d);
}
}
void modify(int u){
int v,t;
pair<int,int> tmp;
while(fa[top[u]]){
t=t1.queryl(1,1,n,dfn[top[u]]+1,dfn[bot[u]]);
if(t==-1){
v=bot[u];
}else{
v=pos[t-1];
}
if(t1.queryl(1,1,n,dfn[top[u]],dfn[top[u]])!=-1){
tmp=make_pair(-inf,0);
}else{
tmp=t3.query(1,1,n,dfn[top[u]],dfn[v]);
}
t3.update(1,1,n,dfn[fa[top[u]]],last[top[u]],tmp);
last[top[u]]=tmp;
u=fa[top[u]];
}
}
void update1(int u,int val){
int v=u,t=u,tmp;
while(t){
tmp=t1.queryr(1,1,n,dfn[top[t]]+1,dfn[t]);
if(tmp!=-1){
v=pos[tmp];
break;
}else if(t1.queryl(1,1,n,dfn[top[t]],dfn[top[t]])!=-1){
v=top[t];
break;
}
t=fa[top[t]];
}
pair<int,int> res=t2.query(1,1,n,dfn[v],dfn[v]+siz[v]-1);
if(res.first+val<0){
t3.update(1,1,n,dfn[u],make_pair(-inf,0),make_pair(val,u));
modify(u);
}else{
ans+=res.first+val;
t2.update(1,1,n,dfn[u],make_pair(-inf,0),make_pair(-val,u));
t2.update(1,1,n,dfn[res.second],make_pair(res.first,res.second),make_pair(-inf,0));
t3.update(1,1,n,dfn[res.second],make_pair(-inf,0),make_pair(-res.first,res.second));
add(u,1,-1);
add(res.second,1,1);
modify(u);
modify(res.second);
}
}
void update2(int u,int val){
int v,t=u,tmp;
pair<int,int> res=make_pair(-inf,0);
while(t){
tmp=t1.queryl(1,1,n,dfn[t]+1,dfn[bot[t]]);
if(tmp==-1){
v=bot[t];
}else{
v=pos[tmp-1];
}
res=max(res,t3.query(1,1,n,dfn[top[t]],dfn[v]));
t=fa[top[t]];
}
if(res.first+val<0){
t2.update(1,1,n,dfn[u],make_pair(-inf,0),make_pair(val,u));
}else{
ans+=res.first+val;
t3.update(1,1,n,dfn[u],make_pair(-inf,0),make_pair(-val,u));
t3.update(1,1,n,dfn[res.second],make_pair(res.first,res.second),make_pair(-inf,0));
t2.update(1,1,n,dfn[res.second],make_pair(-inf,0),make_pair(-res.first,res.second));
add(res.second,1,-1);
add(u,1,1);
modify(res.second);
modify(u);
}
}
int main(){
scanf("%d%d",&n,&q);
for(int i=1;i<n;i++){
scanf("%d%d%d",&u,&v,&d);
adde(u,v,d);
adde(v,u,d);
}
dfs(1);
dfs(1,1);
t2.build(1,1,n);
t3.build(1,1,n);
while(q--){
scanf("%d%d%d",&op,&u,&v);
if(op==1){
update1(u,v-dis[u]);
}else{
update2(u,v+dis[u]);
}
printf("%lld\n",ans);
}
return 0;
}