给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。
冲着树链剖分来的,结果发现自己太弱了操作二的标记不会打,YY了2个多小时才写完QAQ
注意全部操作均为边权,于是要将边权下放到点上,具体看代码
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
const int maxn=210000+10;
struct seg{
int l,r,delta;
seg *lc,*rc;
int mx,mi;
seg():mx(0),mi(0),delta(0){}
};
seg *root=new seg;
int Belong[maxn],deep[maxn],size[maxn];
struct edge{
int to,next,w,f;
}G[maxn*5];
int n,m,q,tot=0,h[maxn];
int fa[maxn][16],pos[maxn];
int ans,ind=0;
bool vis[maxn];
int X[maxn],Y[maxn],Z[maxn];
char ch;
int read(){
int num=0; ch=getchar();
while (ch<'!') ch=getchar();
while (ch>='0'&&ch<='9'){num=num*10+ch-'0';ch=getchar();}
return num;
}
void add(int x,int y,int z){
++tot; G[tot].to=y; G[tot].w=z;
G[tot].next=h[x]; h[x]=tot;
}
void DFS1(int x,int dep){
deep[x]=dep; size[x]=1; vis[x]=1;
for (int i=1;i<=15;++i){
if (deep[x]<(1<break;
fa[x][i]=fa[fa[x][i-1]][i-1];
}
for (int i=h[x];i;i=G[i].next){
int v=G[i].to;
if (vis[v]) continue;
fa[v][0]=x;
DFS1(v,dep+1);
size[x]+=size[v];
}
}
void DFS2(int x,int L){
int k=0; ++ind;
pos[x]=ind;
Belong[x]=L;
for (int i=h[x];i;i=G[i].next)
if (deep[x]size[k])
k=G[i].to;
if (!k) return ;
DFS2(k,L);
for (int i=h[x];i;i=G[i].next)
if (deep[x]*p,int l,int r){
p->l=l; p->r=r;
if (l+1==r) return;
else if (l+1int mid=(l+r)>>1;
p->lc=new seg;
p->rc=new seg;
if (llc,l,mid);
if (midrc,mid,r);
}
}
void updatemax(seg *p){//带懒标记的更新要谨慎……
if (p->l+1==p->r) return;
if (p->lc) p->mx=p->lc->mx;
else{
if (p->rc) p->mx=p->rc->mx;
return;
}
if (p->rc)
p->mx=max(p->mx,p->rc->mx);
}
void updatemin(seg *p){
if (p->l+1==p->r) return;
if (p->lc) p->mi=p->lc->mi;
else{
if (p->rc) p->mi=p->rc->mi;
return;
}
if (p->rc)
p->mi=min(p->mi,p->rc->mi);
}
void Swap(seg *p){
int t=p->mx; p->mx=-p->mi; p->mi=-t;
}
void push_down(seg *p){//注意标记的写法,更新儿子的值
if (!p->delta) return;
else{
p->delta=0;
if (p->l+1==p->r) return;
if (p->lc) p->lc->delta^=1;
if (p->rc) p->rc->delta^=1;
if (p->lc) Swap(p->lc);
if (p->rc) Swap(p->rc);
}
}
void update(seg *p,int pos,int val){
if (p->l+1==p->r){p->mx=p->mi=val;return ;}
else{
int mid=(p->l+p->r)>>1;
if (p->delta) push_down(p);
if (poslc,pos,val);
if (mid<=pos) update(p->rc,pos,val);
updatemax(p); updatemin(p);
}
}
void Qmax(seg *p,int l,int r){//对于这道题要改就改到底,否则会影响程序正确性
if (l<=p->l&&p->r<=r){
push_down(p);
if (p->l+1==p->r){
ans=max(ans,p->mx);
return;
}
if (p->lc) Qmax(p->lc,l,r);
if (p->rc) Qmax(p->rc,l,r);
updatemax(p); updatemin(p);
ans=max(ans,p->mx);
}else{
push_down(p);
if (p->l+1==p->r) return;
int mid=(p->l+p->r)>>1;
if (llc,l,r);
if (midrc,l,r);
updatemax(p); updatemin(p);
}
}
void change(seg *p,int l,int r){
if (l<=p->l&&p->r<=r){
p->delta^=1;
if (p->l+1==p->r){Swap(p);}
return;}
else{
if (p->delta) push_down(p);
int mid=(p->l+p->r)>>1;
if (llc,l,r);
if (midrc,l,r);
updatemax(p); updatemin(p);
}
}
int solve(int u,int v){
int sum=-100000000;
bool flag=0;
if (u==9) flag=1;
while (Belong[u]!=Belong[v]){
ans=-100000000;
Qmax(root,pos[Belong[u]],pos[u]+1);
sum=max(sum,ans); u=fa[Belong[u]][0];
}
ans=-100000000; Qmax(root,pos[v]+1,pos[u]+1);//注意这里的pos[v]+1
sum=max(sum,ans); return sum;
}
int LCA(int a,int b){
if (deep[a]int t=deep[a]-deep[b];
for (int i=0;i<=15;++i)
if (t&(1<for (int i=15;~i;i--)
if (fa[a][i]!=fa[b][i]){
a=fa[a][i];b=fa[b][i];}
if (a==b) return a;
else return fa[a][0];
}
void Fchange(int u,int v){
while (Belong[u]!=Belong[v]){
change(root,pos[Belong[u]],pos[u]+1);
u=fa[Belong[u]][0];
if (u==0) return;
}
change(root,pos[v]+1,pos[u]+1);
}
int main(){
freopen("maintaintree.in","r",stdin);
freopen("maintaintree.out","w",stdout);
n=read();
for (int i=1;iint x,y,z;
x=read(); y=read(); z=read();
add(x,y,z); add(y,x,z);
X[i]=x; Y[i]=y; Z[i]=z;
}
DFS1(1,1);
DFS2(1,1);
build(root,1,ind+1);
update(root,pos[1],-100000000);
for (int i=1;iint u=X[i],v=Y[i],w=Z[i];
if (deep[u]pos[u],w);
}
char ch[10]; int x,y;
while (scanf("%s",ch)==1){
if (ch[0]=='D') break;
x=read(); y=read();
if (ch[0]=='C'){//边权下放到深儿子上
int a=X[x],b=Y[x],Aim;
if(deep[a]>deep[b])Aim=a;else Aim=b;
Z[Aim]=y; update(root,pos[Aim],y);
}else if (ch[0]=='N'){
int zx=LCA(x,y);
Fchange(x,zx); Fchange(y,zx);
}else{
int zx=LCA(x,y);
printf("%d\n",max(solve(x,zx),solve(y,zx)));
}
}
//碉堡啦!
}