题意:在树上操作,每次将两点路径值全变负和单点修改。每次求两点间路径的最大值。
思路:
边权转点权的话,每次把一条边的儿子点作为该边的权值。想起来挺好想,很容易出问题。
查询修改的话,要将多算的那条lca去掉就可以了。剩下的就是板子。
总结:
- 去掉lca,只需要判断top[x]==top[y]时,x和y是否相等,不等把deep浅的点+1即可。
- 边权转点权,因为你不知道谁是谁的父亲,所以要树刨完或者第一遍dfs完建点权和树,单点修改也是。
代码:
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<string>
#include<cstring>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<cmath>
#include<sstream>
using namespace std;
#define ll long long
#define forn(i,n) for(int i=0;i<n;i++)
#define for1(i,n) for(int i=1;i<=n;i++)
#define IO ios::sync_with_stdio(false);cin.tie(0)
const int maxn = 1e4+5;
const int inf = 0x3f3f3f3f;
int a[maxn],top[maxn],p[maxn],sz[maxn],par[maxn],son[maxn],deep[maxn],fp[maxn],id,now;
pair<pair<int,int>,int>g[maxn];
vector<int>e[maxn];
class segment_tree{
public:
#define nd node[now]
#define ndl node[now<<1]
#define ndr node[now<<1|1]
struct segment_node{
int l,r,v,V,flag;
void update(){
flag^=1;
v=-v,V=-V;
swap(v,V);
}
}node[maxn<<2];
void pushup(int now){
nd.v = min(ndl.v,ndr.v);
nd.V = max(ndl.V,ndr.V);
}
void pushdown(int now){
if(nd.flag){
ndl.update();
ndr.update();
nd.flag = 0