树链剖分
增加一个或删除一个点
1.如果有其他路径经过它,它就对答案没有影响
2.其他情况就各种找lca
反正我已经看不懂我的代码了,就酱
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
typedef __int64 LL;
const int N=1e5+100;
const int INF=0x3f3f3f3f;
#define ll o<<1
#define rr o<<1|1
#define mid (l+r)/2
struct Edge {
int v,next,w;
Edge(){}
Edge(int v,int next,int w):v(v),next(next),w(w){}
}e[N*2];
int head[N],total;
void init(){
memset(head,-1,sizeof(head));total=0;
}
void adde(int u,int v,int w){
e[total]=Edge(v,head[u],w);head[u]=total++;
}
int dep[N],sz[N],fa[N],son[N];
int st[N],ed[N],ti,fst[N];LL dis[N];
void getson(int u,int f){///�ض���
//printf("getson %d %d\n",u,f);
dep[u]=dep[f]+1;sz[u]=1;fa[u]=f;son[u]=-1;
st[u]=++ti;fst[ti]=u;
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v==f)continue;
dis[v]=dis[u]+e[i].w;
getson(v,u);
sz[u]+=sz[v];
if(son[u]==-1||sz[son[u]]<sz[v])son[u]=v;
}
ed[u]=ti;
}
int top[N],p[N],fp[N],pos;
void getpos(int u,int clo){////������p������
top[u]=clo;
p[u]=++pos;
fp[pos]=u;
if(son[u]==-1)return ;
getpos(son[u],clo);
for(int i=head[u];i!=-1;i=e[i].next){
int v=e[i].v;
if(v!=son[u]&&v!=fa[u]){
getpos(v,v);
}
}
}
////////seg_tree;
int mx[N<<2],add[N<<2];
void pushdown(int l,int r,int o){
if(add[o]){
add[ll]+=add[o];
add[rr]+=add[o];
mx[ll]+=add[o];
mx[rr]+=add[o];
add[o]=0;
}
}
void pushup(int l,int r,int o){
mx[o]=max(mx[ll],mx[rr]);
}
int L,R,V,opx;
void update(int l,int r,int o){
//printf("update%d %dLR,%d %dlr,%d %dVopx\n",L,R,l,r,V,opx);
if(L<=l&&r<=R){
add[o]+=V;
mx[o]+=V;
return ;
}
pushdown(l,r,o);
if(L<=mid)update(l,mid,ll);
if(R>mid)update(mid+1,r,rr);
pushup(l,r,o);
}
int query(int l,int r,int o){
//printf("query%d %dLR,%d %d %d %d\n",L,R,l,r,V,opx);
if(l==r){
if(V==-1)return mx[o];
else if(mx[o]>=V)return l;
else return opx;
}
if(L<=l&&r<=R){
if(V==-1)return mx[o];
else if(opx==-1){
pushdown(l,r,o);
if(mx[rr]>=V) return query(mid+1,r,rr);
else if(mx[ll]>=V) return query(l,mid,ll);
else return -1;
}
else {
pushdown(l,r,o);
if(mx[ll]>=V)return query(l,mid,ll);
else if(mx[rr]>=V)return query(mid+1,r,rr);
else return opx;
}
}
pushdown(l,r,o);
int ans=opx;
if(V==-1){
if(L<=mid)ans=max(ans,query(l,mid,ll));
if(R>mid)ans=max(ans,query(mid+1,r,rr));
}
else if(opx==-1){
if(R>mid)ans=max(ans,query(mid+1,r,rr));
if(ans==-1&&L<=mid)ans=max(ans,query(l,mid,ll));
}
else {
if(L<=mid)ans=min(ans,query(l,mid,ll));
if(ans==INF&&R>mid)ans=min(ans,query(mid+1,r,rr));
}
return ans;
}
int lca(int u,int v,int op,int vx){
int fu=top[u],fv=top[v];
int ans=vx;
//printf("%d %dufu,%d %dfv,%dop %dvx\n",u,fu,v,fv,op,vx);
while(fu!=fv){
if(op==-2){
L=p[fu],R=p[u],V=vx,opx=vx;update(1,pos,1);
}
else if(op==-1){
L=p[fu],R=p[u],V=-1,opx=vx;ans=max(ans,query(1,pos,1));
}
else{
L=p[fu],R=p[u],V=op,opx=vx;
if(opx==-1){
ans=query(1,pos,1);
if(ans!=-1)return fp[ans];
}
else {
ans=min(ans,query(1,pos,1));
}
}
u=fa[fu];fu=top[u];
}
swap(u,v);
if(op==-2){//////// change
L=p[u],R=p[v],V=vx,opx=vx;update(1,pos,1);
}
else if(op==-1){ ///////// query max
L=p[u],R=p[v],V=-1,opx=vx;
ans=max(ans,query(1,pos,1));
}
else { ///////// query >=op id
L=p[u],R=p[v],V=op,opx=vx;
if(opx==-1){
ans=max(ans,query(1,pos,1));
//printf("%dans\n",ans);
if(ans!=-1)ans=fp[ans];
}
else {
ans=min(ans,query(1,pos,1));
if(ans!=INF)ans=fp[ans];
}
}
return ans;
}
void solve(){
pos=0;
dep[0]=0;
dis[1]=0;ti=0;/////////
getson(1,0);
getpos(1,1);
}
int cc[N<<2];
void ucc(int l,int r,int o,int x,int op){
if(l==r){
if(op==1)cc[o]=x;
else cc[o]=INF;
return ;
}
if(x<=mid)ucc(l,mid,ll,x,op);
else ucc(mid+1,r,rr,x,op);
cc[o]=min(cc[ll],cc[rr]);
}
int qcc(int l,int r,int o){
//printf("%d %dlr%d %dLR\n",l,r,L,R);
if(L<=l&&r<=R){
return cc[o];
}
int ans=INF;
if(L<=mid)ans=qcc(l,mid,ll);
if(ans==INF&&R>mid)ans=qcc(mid+1,r,rr);
return ans;
}
int main(){
#ifdef DouBi
freopen("in.cpp","r",stdin);
//freopen("out.cpp","w",stdout);
#endif // DouBi
int n;
while(scanf("%d",&n)!=EOF){
init();
for(int i=1;i<n;i++){
int a,b,c;scanf("%d%d%d",&a,&b,&c);
adde(a,b,c);adde(b,a,c);
}
solve();
//printf("sovle\n");
memset(cc,0x3f,sizeof(cc));
//printf("%d %d\n",cc[1],INF);
memset(add,0,sizeof(add));
memset(mx,0,sizeof(mx));
//for(int i=1;i<=n;i++)printf("%I64d %d %d\n",dis[i],son[i],fa[i]);
//for(int i=1;i<=n;i++)printf("st%d ed%d\n",st[i],ed[i]);printf("%dti\n",ti);
int q;scanf("%d",&q);
LL sum=0;
lca(1,1,-2,1);
int num=0;
while(q--){
char op[10];int x;
scanf("%s",op);
if(n==1){
if(op[0]=='?')printf("0\n");
else scanf("%d",&x);
continue;
}
if(op[0]=='?'){
int xx=lca(1,1,-1,-1);
if(xx>=3)printf("%I64d\n",sum);
else if(xx==1)printf("0\n");
else {
x=1;
lca(x,x,-2,-1);
////////
L=st[x]+1,R=ed[x];
int z1=qcc(1,ti,1);
if(z1==INF){
printf("0\n");
}
else {
LL zz;
int y1=lca(fst[z1],1,-1,-1);
if(y1>=2){
int id=lca(fst[z1],1,2,INF);
zz=dis[id];
}
else {
zz=dis[fst[z1]];
}
printf("%I64d\n",sum-zz);
}
lca(x,x,-2,1);
}
}
else {
scanf("%d",&x);
if(op[0]=='+'){
num++;
if(x==1){
lca(x,x,-2,1);
}
else {
int y=lca(x,x,-1,-1);
if(y>=1){
lca(x,x,-2,1);
}
else {
int id=lca(fa[x],1,1,-1);
lca(x,id,-2,1);
sum+=dis[x]-dis[id];
}
}
ucc(1,ti,1,st[x],1);
}
else {
num--;
if(x==1){
lca(x,x,-2,-1);
}
else {
int y=lca(x,x,-1,-1);
if(y>=2){
lca(x,x,-2,-1);
}
else {
int id=lca(fa[x],1,2,-1);
lca(x,id,-2,-1);
sum-=dis[x]-dis[id];
}
}
ucc(1,ti,1,st[x],-1);
}
}
// for(int i=1;i<=n;i++){
// int xx=lca(i,i,-1,-1);
// printf("%d:%d ",i,xx);
// }printf("\n");
// printf("%s %d .........\n",op,op[0]=='?'?-1:x);
}
}
return 0;
}