今天一天效率好低,好多时间被浪费了,而且还玩儿了两局lol,虽然都赢了,而且都是MVP…肚子疼了好长时间…感觉人都疼瘦了…
这道题最后是一个智障错误…
【题目描述】
给你由N个结点组成的树。树的节点被编号为1到N,边被编号为1到N-1。每一条边有一个权值。然后你要在树上执行一系列指令。指令可以是如下三种之一:
CHANGE i v:将第i条边的权值改成v。
NEGATE a b:将点a到点b路径上所有边的权值变成其相反数。
QUERY a b:找出点a到点b路径上各边的最大权值。
【输入格式】
输入文件的第一行有一个整数N(N<=10000)。
接下来N-1行每行有三个整数a,b,c,代表点a和点b之间有一条权值为c的边。这些边按照其编号从小到大给出。
接下来是若干条指令(不超过10^5条),都按照上面所说的格式。
输入文件的最后一行是”DONE”.
【输出格式】
对每个“QUERY”指令,输出一行,即路径上各边的最大权值。
【样例输入】
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
【样例输出】
1
3
【提示】
这里的输入输出格式和POJ上原题略有不同。
【来源】
POJ 3237 Tree
COGS上测的
【题解】
直接树链剖分然后线段树维护就行了,也是裸题,值得注意的是边权下放操作以及在两个dfs之后对于每一条边的from置为from和to中浅的那个,to为深的那个,然后线段树维护的时候维护一个max值一个min值,进行取反操作的时候,对于一个需要取反的区间,原来的max值的相反数变成新的min值,原来的min值的相反数变成新的max值,然后给该区间打上标记即可,所以尤其要注意pushdown的操作,其他的应该没什么了,就可以过啦
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<vector>
#include<map>
#include<set>
const int MAXN = 10000+50;
using namespace std;
int readin(){
int x=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9')ch=getchar();
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
struct Line{
int from,to,nxt,val;
}line[MAXN*2];
int value[MAXN];
int head[MAXN],tail=0;
int dep[MAXN],fa[MAXN],siz[MAXN],son[MAXN],top[MAXN],tid[MAXN],rank[MAXN],timer;
int mark[MAXN*4],maxn[MAXN*4],minn[MAXN*4],n;
void add_line(int from,int to,int val){
tail++;
line[tail].to=to;
line[tail].val=val;
line[tail].nxt=head[from];
line[tail].from=from;
head[from]=tail;
}
void dfs1(int u,int father,int d){
dep[u]=d;
fa[u]=father;
siz[u]=1;
for(register int i=head[u];i;i=line[i].nxt){
int v=line[i].to;
if(v!=father){
value[v]=line[i].val;
dfs1(v,u,d+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[son[u]]<siz[v]) son[u]=v;
}
}
}
void dfs2(int u,int tp){
top[u]=tp;
tid[u]=++timer;
rank[tid[u]]=u;
if(son[u]==-1) return;
dfs2(son[u],tp);
for(register int i=head[u];i;i=line[i].nxt){
int v=line[i].to;
if(v!=fa[u]&&v!=son[u]) dfs2(v,v);
}
}
void pushup(int rt){
maxn[rt]=max(maxn[rt<<1|1],maxn[rt<<1]);
minn[rt]=min(minn[rt<<1|1],minn[rt<<1]);
}
void pushdown(int rt,int len){
if(mark[rt]){
mark[rt<<1]=mark[rt<<1]^1;
mark[rt<<1|1]=mark[rt<<1|1]^1;
mark[rt]=mark[rt]^1;
int t=maxn[rt<<1];
maxn[rt<<1]=-minn[rt<<1];
minn[rt<<1]=-t;
t=maxn[rt<<1|1];
maxn[rt<<1|1]=-minn[rt<<1|1];
minn[rt<<1|1]=-t;
}
}
void build(int l,int r,int rt){
mark[rt]=0;
if(l==r){
maxn[rt]=value[rank[l]];
minn[rt]=value[rank[l]];
return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
pushup(rt);
}
void modify(int loc,int val,int l,int r,int rt){
if(l==r){
maxn[rt]=val;
minn[rt]=val;
return;
}
int mid=(l+r)>>1;
pushdown(rt,r-l+1);
if(loc<=mid) modify(loc,val,l,mid,rt<<1);
else modify(loc,val,mid+1,r,rt<<1|1);
pushup(rt);
}
void update(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r){
int t=maxn[rt];
maxn[rt]=-minn[rt];
minn[rt]=-t;
mark[rt]=mark[rt]^1;
return;
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
if(L<=mid) update(L,R,l,mid,rt<<1);
if(R>mid) update(L,R,mid+1,r,rt<<1|1);
pushup(rt);
}
void _modify(int from,int to){
while(top[from]!=top[to]){
if(dep[top[from]]<dep[top[to]])swap(from,to);
update(tid[top[from]],tid[from],1,n,1);
from=fa[top[from]];
}
if(dep[from]<dep[to]) swap(from,to);
if(from!=to) update(tid[son[to]],tid[from],1,n,1);
}
int query(int L,int R,int l,int r,int rt){
if(L<=l&&R>=r){
return maxn[rt];
}
pushdown(rt,r-l+1);
int mid=(l+r)>>1;
int Mx=-0x7fffffff;
if(L<=mid) Mx=max(Mx,query(L,R,l,mid,rt<<1));
if(R>mid) Mx=max(Mx,query(L,R,mid+1,r,rt<<1|1));
pushup(rt);
return Mx;
}
void _query(int from,int to){
int maxnn=-0x7fffffff;
while(top[from]!=top[to]){
if(dep[top[from]]<dep[top[to]])swap(from,to);
maxnn=max(maxnn,query(tid[top[from]],tid[from],1,n,1));
from=fa[top[from]];
}
if(dep[from]<dep[to]) swap(from,to);
if(from!=to) maxnn=max(maxnn,query(tid[son[to]],tid[from],1,n,1));
printf("%d\n",maxnn);
}
int main(){
freopen("maintaintree.in","r",stdin);
freopen("maintaintree.out","w",stdout);
memset(son,-1,sizeof(son));
scanf("%d",&n);
int from,to,val;
for(register int i=1;i<=n-1;i++){
scanf("%d%d%d",&from,&to,&val);
add_line(from,to,val);add_line(to,from,val);
}
dfs1(1,0,0);
dfs2(1,1);
for(register int i=1;i<=tail;i++) if(dep[line[i].to]<dep[line[i].from]) swap(line[i].to,line[i].from);
build(1,n,1);
char qq[10];
int a,b;
scanf("%s",qq);
while(qq[0]!='D'){
if(qq[0]=='Q'){
scanf("%d%d",&a,&b);
_query(a,b);
}else if(qq[0]=='C'){
scanf("%d%d",&a,&b);
int _to=line[a*2].to;
modify(tid[_to],b,1,n,1);
}else{
scanf("%d%d",&a,&b);
_modify(a,b);
}
scanf("%s",qq);
}
return 0;
}