P1505 [国家集训队]旅游(树剖板题)
Posted Harris-H
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P1505 [国家集训队]旅游(树剖板题)相关的知识,希望对你有一定的参考价值。
P1505 [国家集训队]旅游(树剖板题)
1.边权转点权。
dfs时边下放到点就行了,因为每个点的父边唯一。
2.然后就是裸的线段树了,区间翻转,区间最值,单点修改,没了。
3.码农题好想吐槽啊。
// Problem: P1505 [国家集训队]旅游
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1505
// Memory Limit: 256 MB
// Time Limit: 1000 ms
// Date: 2021-08-18 11:54:24
// --------by Herio--------
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=2e5+5,M=2e4+5,inf=0x3f3f3f3f,mod=1e9+7;
#define mst(a,b) memset(a,b,sizeof a)
#define PII pair<int,int>
#define fi first
#define se second
#define pb emplace_back
#define SZ(a) (int)a.size()
#define ios ios::sync_with_stdio(false),cin.tie(0)
void Print(int *a,int n){
for(int i=1;i<n;i++)
printf("%d ",a[i]);
printf("%d\\n",a[n]);
}
//区间修改 区间求和
#define il inline
#define lx x<<1
#define rx x<<1|1
#define len(x) (a[x].r-a[x].l+1)
int w[N];
struct node{
int l,r,lz;
int s,mx,mn;
}a[N<<2];
il void re(int x){
a[x].s=a[lx].s+a[rx].s;
a[x].mx=max(a[lx].mx,a[rx].mx);
a[x].mn=min(a[lx].mn,a[rx].mn);
}
il void ptg(int x){
a[x].lz^=1;
a[x].s=-a[x].s,a[x].mx=-a[x].mx,a[x].mn=-a[x].mn;
swap(a[x].mx,a[x].mn);
}
il void pd(int x){
if(a[x].lz){
ptg(lx),ptg(rx);
a[x].lz=0;
}
}
il void bud(int x,int l,int r){
a[x].l=l,a[x].r=r;
if(l==r){
a[x].s=a[x].mx=a[x].mn=w[l];
return;
}
int m=(l+r)>>1;bud(lx,l,m),bud(rx,m+1,r);
re(x);
}
il void upd(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r){
ptg(x);return;
}
pd(x);
int m=(a[x].l+a[x].r)>>1;
if(l<=m) upd(lx,l,r);
if(r>m) upd(rx,l,r);
re(x);
}
il void update(int x,int p,int v){
//printf("%d %d %d\\n",x,p,v);
if(a[x].l==a[x].r){
a[x].mx=a[x].mn=a[x].s=v;return;
}
pd(x);
int m=(a[x].l+a[x].r)>>1;
if(p<=m) update(lx,p,v);
else update(rx,p,v);
re(x);
}
il int que(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].s;
pd(x);
int m=(a[x].l+a[x].r)>>1;int ans=0;
if(l<=m) ans+=que(lx,l,r);
if(r>m) ans+=que(rx,l,r);
return ans;
}
il int quemx(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].mx;
pd(x);
int m=(a[x].l+a[x].r)>>1;int ans=-inf;
if(l<=m) ans=max(ans,quemx(lx,l,r));
if(r>m) ans=max(ans,quemx(rx,l,r));
return ans;
}
il int quemn(int x,int l,int r){
if(a[x].l>=l&&a[x].r<=r) return a[x].mn;
pd(x);
int m=(a[x].l+a[x].r)>>1;int ans=inf;
if(l<=m) ans=min(ans,quemn(lx,l,r));
if(r>m) ans=min(ans,quemn(rx,l,r));
return ans;
}
//树剖
struct edge{
int to,nt,w;
}e[N<<1];
int h[N],cnt=1;
void add(int u,int v,int w){
e[++cnt]={v,h[u],w},h[u]=cnt;
e[++cnt]={u,h[v],w},h[v]=cnt;
}
int sz[N],fa[N],son[N],top[N],dfn[N],dep[N];
int ys[N];
void dfs(int u,int f){
sz[u]=1,fa[u]=f,dep[u]=dep[f]+1;
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to;
if(v==f) continue;
dfs(v,u);
ys[v]=e[i].w;
sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
}
int id;
void dfs1(int u,int tp){
top[u]=tp,dfn[u]=++id;w[id]=ys[u];
if(son[u]) dfs1(son[u],tp);
for(int i=h[u];i;i=e[i].nt){
int v=e[i].to;
if(v!=fa[u]&&v!=son[u]) dfs1(v,v);
}
}
int upd_c(int x,int y){ //chain update
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
upd(1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(y!=x) upd(1,dfn[y]+1,dfn[x]);
}
int que_cs(int x,int y){ //chain query
int ans=0;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=ans+que(1,dfn[top[x]],dfn[x]);
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(y!=x) ans=ans+que(1,dfn[y]+1,dfn[x]);
return ans;
}
int que_cmn(int x,int y){ //chain query
int ans=inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=min(ans,quemn(1,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(y!=x) ans=min(ans,quemn(1,dfn[y]+1,dfn[x]));
return ans;
}
int que_cmx(int x,int y){ //chain query
int ans=-inf;
while(top[x]!=top[y]){
if(dep[top[x]]<dep[top[y]]) swap(x,y);
ans=max(ans,quemx(1,dfn[top[x]],dfn[x]));
x=fa[top[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(y!=x) ans=max(ans,quemx(1,dfn[y]+1,dfn[x]));
return ans;
}
PII ee[N];
int main(){
int n,q;scanf("%d",&n);
for(int i=1,u,v,w;i<n;i++){
scanf("%d%d%d",&u,&v,&w),u++,v++;
ee[i]={u,v};
add(u,v,w);
}
dfs(1,0),dfs1(1,0);bud(1,1,n);
//Print(dep,n);return 0;
scanf("%d",&q);while(q--){
char op[5];int u,v;
scanf("\\n%s%d%d",op,&u,&v);
if(op[0]!='C') u++,v++;
if(op[0]=='C'){
int x=dep[ee[u].fiLUOGU P1505 [国家集训队]旅游 (树链剖分+线段树)