边权放到下面的点上,统计/修改时不算他俩的LCA
Add时:
①上面已经有覆盖标记——覆盖标记+k
②没有覆盖标记——加标记+k
覆盖时
①上面已经有加标记——加标记清零,覆盖标记打上
①上面没有加标记——加标记清零,覆盖标记打上…
代码如下:
#include<algorithm>
#include<ctype.h>
#include<cstdio>
#define N 100020
using namespace std;
const int base=-2147483647;
inline int read(){
int x=0,f=1;char c;
do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c));
do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c));
return x*f;
}
int n,x,y,k,Top,T;
int w[N],pre[N],tree[N],fa[N],dep[N],son[N],top[N],fir[N],siz[N];
char c[15];
struct Edge{
int to,nex,k;
Edge(int _=0,int __=0,int ___=0):to(_),nex(__),k(___){}
}nex[N<<1];
struct Table{
int x,y,k;
}a[N];
struct Node{
int l,r,addv,v;
int maxx;
Node *ls,*rs;
inline void maintain(){
if(l==r) return;
maxx=max(ls->maxx,rs->maxx);
}
inline void Pushdown(){
if(l==r) return;
if(v!=base){
ls->v=v;ls->maxx=v;
rs->v=v;rs->maxx=v;
addv=0;v=base;
return;
}
else if(addv){
ls->maxx+=addv;
if(ls->v!=base) ls->v+=addv;
ls->addv+=addv;
rs->maxx+=addv;
if(rs->v!=base) rs->v+=addv;
rs->addv+=addv;
addv=0;v=base;
return;
}
}
}*root;
inline void add(int x,int y,int k){
nex[++Top]=Edge(y,fir[x],k);
fir[x]=Top;
}
void dfs1(int x,int Dep,int Fa){
fa[x]=Fa;dep[x]=Dep;
siz[x]=1;
for(int i=fir[x];i;i=nex[i].nex){
if(nex[i].to==Fa) continue;
dfs1(nex[i].to,Dep+1,x);
w[nex[i].to]=nex[i].k;
siz[x]+=siz[nex[i].to];
if(siz[nex[i].to]>siz[son[x]]) son[x]=nex[i].to;
}
}
void dfs2(int x,int Top){
top[x]=Top;
tree[x]=++T;pre[T]=x;
if(!son[x]) return;
dfs2(son[x],Top);
for(int i=fir[x];i;i=nex[i].nex){
if(nex[i].to==fa[x] || nex[i].to==son[x]) continue;
dfs2(nex[i].to,nex[i].to);
}
}
void maketree(int l,int r,Node *k){
k->l=l;k->r=r;
k->v=base;k->addv=0;
if(l==r){
k->maxx=w[pre[l]];
return;
}
int mid=l+r>>1;
maketree(l,mid,k->ls=new Node);maketree(mid+1,r,k->rs=new Node);
k->maintain();
}
void Add(int l,int r,int x,Node *k){
if(k->l>=l && k->r<=r){
if(k->v!=base)
k->v+=x;
else k->addv+=x;
k->maxx+=x;
return;
}
int mid=k->l+k->r>>1;
k->Pushdown();
if(r<=mid) Add(l,r,x,k->ls);
else if(l>mid) Add(l,r,x,k->rs);
else Add(l,r,x,k->ls),Add(l,r,x,k->rs);
k->maintain();
}
void Modify(int l,int r,int x,Node *k){
if(k->l>=l && k->r<=r){
k->v=x;k->addv=0;
k->maxx=x;
return;
}
int mid=k->l+k->r>>1;
k->Pushdown();
if(r<=mid) Modify(l,r,x,k->ls);
else if(l>mid) Modify(l,r,x,k->rs);
else Modify(l,r,x,k->ls),Modify(l,r,x,k->rs);
k->maintain();
}
int Query_Max(int l,int r,Node *k){
if(k->l>=l && k->r<=r){
return k->maxx;
}
k->Pushdown();
int mid=k->l+k->r>>1,t;
if(r<=mid) t=Query_Max(l,r,k->ls);
else if(l>mid) t=Query_Max(l,r,k->rs);
else t=max(Query_Max(l,r,k->ls),Query_Max(l,r,k->rs));
return t;
}
inline void Modify_Tree(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
Modify(tree[top[x]],tree[x],k,root);
x=fa[top[x]];
}
if(x==y) return;
if(tree[x]>tree[y]) swap(x,y);
Modify(tree[x]+1,tree[y],k,root);
}
inline void Add_Tree(int x,int y,int k){
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
Add(tree[top[x]],tree[x],k,root);
x=fa[top[x]];
}
if(x==y) return;
if(tree[x]>tree[y]) swap(x,y);
Add(tree[x]+1,tree[y],k,root);
}
inline int Max_Tree(int x,int y){
int maxx=base;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
maxx=max(maxx,Query_Max(tree[top[x]],tree[x],root));
x=fa[top[x]];
}
if(x==y) return maxx;
if(tree[x]>tree[y]) swap(x,y);
maxx=max(maxx,Query_Max(tree[x]+1,tree[y],root));
return maxx;
}
inline void Debug1(){
printf("\nTree Pow:\n\n");
for(int i=1;i<=n;i++){
printf("id:%d tree:%d son:%d siz:%d top:%d\n",i,tree[i],son[i],siz[i],top[i]);
}
for(int i=1;i<=n;i++) printf("%d ",pre[i]);
printf("\nTree Pow End.\n\n");
}
void dfs(Node *x){
if(!x) return;
x->Pushdown();
printf("l:%d r:%d v:%d addv:%d maxx:%d\n",x->l,x->r,x->v,x->addv,x->maxx);
dfs(x->ls);dfs(x->rs);
}
inline void Debug2(){
printf("\nSegment Tree:\n\n");
dfs(root);
printf("\n\n");
}
int main(){
n=read();
for(int i=1;i<n;i++){
x=read();y=read();k=read();
a[i].x=x;a[i].y=y;a[i].k=k;
add(x,y,k);add(y,x,k);
}
dfs1(1,1,0);dfs2(1,1);
maketree(1,n,root=new Node);
while(""){
scanf("%s",c+1);
if(c[1]=='C'){
if(c[2]=='o'){
x=read();y=read();k=read();
Modify_Tree(x,y,k);
}
else{
x=read();k=read();
y=a[x].y;x=a[x].x;
if(dep[x]<dep[y]) swap(x,y);
Modify(tree[x],tree[x],k,root);
}
}
else if(c[1]=='A'){
x=read();y=read();k=read();
Add_Tree(x,y,k);
}
else if(c[1]=='M'){
x=read();y=read();
printf("%d\n",Max_Tree(x,y));
}
else break;
}
return 0;
}
sb才这么写调半天
想骂人
附上一组小数据生成器:
#include<bits/stdc++.h>
#define random(a,b) ((a)+rand()%((b)-(a)+1))
using namespace std;
const int N=10;
const int M=15;
stringstream str;
int x,y,n,m,t,seed;
int f[N];
int find(int x){return f[x]==x?f[x]:f[x]=find(f[x]);}
int main(int argc,char *argv[]){
seed=time(NULL);
if(argc){
str.clear();
str<<argv[1];
str>>seed;
}
srand(seed);
n=random(1,N);
for(int i=1;i<=n;i++) f[i]=i;
printf("%d\n",n);
for(int cnt=1;cnt<n;){
x=rand()%n+1;y=rand()%n+1;
int fx=find(x),fy=find(y);
if(fx==fy){continue;}
f[fy]=fx;
printf("%d %d",x,y);
printf(" %d",rand()%10+1);
puts("");
cnt++;
}
m=rand()%10;
for(int i=1;i<=m;i++){
t=rand()%4+1;
if(t==1){
printf("Change %d %d\n",rand()%(n-1)+1,rand()%10+1);
}
else if(t==2){
do x=rand()%n+1,y=rand()%n+1; while(x==y);
printf("Cover %d %d %d\n",x,y,rand()%10+1);
}
else if(t==3){
do x=rand()%n+1,y=rand()%n+1; while(x==y);
printf("Max %d %d\n",x,y);
}
else if(t==4){
do x=rand()%n+1,y=rand()%n+1; while(x==y);
printf("Add %d %d %d\n",x,y,rand()%10+1);
}
}
printf("Stop");
return 0;
}