社区讨论
萌新妺子没学oi,简单树剖板子过样例但全 WA
P1505[国家集训队] 旅游参与者 3已保存回复 2
讨论操作
快速查看讨论及其快照的属性,并进行相关操作。
- 当前回复
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @lrln3phf
- 此快照首次捕获于
- 2024/01/20 13:39 2 年前
- 此快照最后确认于
- 2024/01/20 16:27 2 年前
求调教,悬赏一关注
CPP#include <bits/stdc++.h>
using namespace std;
const int N=2e5+10,INF=2e9+10;
struct Edge
{
int v,w;
}edge;
struct PII
{
int x,y;
};
vector<Edge> e[N];
int dep[N],siz[N],son[N],top[N],f[N],a[N];
int dfn[N],idx[N],tot;
int sum[N<<2],tag[N<<2],Max[N<<2],Min[N<<2];
struct PII t[N]; //边对应第几个输入
int n,m;
void dfs_1(int u,int fa)
{
dep[u] = dep[fa] + 1 , siz[u] = 1 , f[u] = fa;
for(auto t : e[u])
{
if(t.v!=fa)
{
dfs_1(t.v,u) , siz[u] += siz[t.v] , a[t.v] = t.w;
if(siz[son[u]] < siz[t.v]) son[u] = t.v;
}
}
}
void dfs_2(int u,int topx)
{
top[u] = topx , dfn[u] = ++tot , idx[tot] = a[u];
if(!son[u]) return ;
dfs_2(son[u],topx);
for(auto t : e[u])
{
if(t.v!=f[u] && t.v!=son[u])
dfs_2(t.v,t.v);
}
}
#define mid ((l+r)/2)
#define ls u<<1
#define rs u<<1|1
void pushup(int u)
{
sum[u] = sum[ls] + sum[rs];
Min[u] = min(Min[ls] , Min[rs]);
Max[u] = max(Max[ls] , Max[rs]);
}
void pushdown(int u)
{
if(!tag[u]) return ;
tag[ls]^=1 , tag[rs]^=1;
swap(Max[ls],Min[ls]);
swap(Max[rs],Min[rs]);
Max[ls] *= (-1) , Min[ls] *= (-1);
Max[rs] *= (-1) , Min[rs] *= (-1);
sum[ls] *= (-1) , sum[rs] *= (-1);
tag[u] ^= 1;
}
void build(int u,int l,int r)
{
Min[u] = INF , Max[u] = -INF;
if(l==r)
{
sum[u] = Max[u] = Min[u] =idx[l] ;
return ;
}
build(ls,l,mid) , build(rs,mid+1,r);
pushup(u);
}
//将区间改为相反数
void change(int u,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr)
{
tag[u]^=1 , sum[u] *= (-1);
swap(Min[u],Max[u]);
Min[u] *= (-1) , Max[u] *= (-1) ;
return ;
}
pushdown(u);
if(ql<=mid) change(ls,l,mid,ql,qr) ;
if(mid+1<=qr) change(rs,mid+1,r,ql,qr);
pushup(u);
}
void change(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
change(1,1,n,dfn[top[x]],dfn[x]);
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
if(x!=y)
change(1,1,n,dfn[x]+1,dfn[y]);
}
//单点修改
void change_one(int u,int l,int r,int p,int k)
{
if(l==r)
{
sum[u] = Min[u] = Max[u] = k ;
return ;
}
pushdown(u);
if(p<=mid) change_one(ls,l,mid,p,k);
else change_one(rs,mid+1,r,p,k);
pushup(u);
}
//询问最大值
int ask_max(int u,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr) return Max[u];
pushdown(u);
int s = -INF;
if(ql<=mid) s = max(s,ask_max(ls,l,mid,ql,qr));
if(mid+1<=qr) s = max(s,ask_max(rs,mid+1,r,ql,qr));
return s;
}
int ask_max(int x,int y)
{
int s = -INF;
while(top[x]!=top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
s = max(s,ask_max(1,1,n,dfn[top[x]],dfn[x]));
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
if(x!=y)
s = max(s,ask_max(1,1,n,dfn[x]+1,dfn[y]));
return s;
}
//询问最小值
int ask_min(int u,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr) return Min[u];
pushdown(u);
int s = INF;
if(ql<=mid) s = min(s,ask_min(ls,l,mid,ql,qr));
if(mid+1<=qr) s = min(s,ask_min(rs,mid+1,r,ql,qr));
return s;
}
int ask_min(int x,int y)
{
int s = INF;
while(top[x]!=top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
s = min(s,ask_min(1,1,n,dfn[top[x]],dfn[x]));
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
if(x!=y)
s = min(s,ask_min(1,1,n,dfn[x]+1,dfn[y]));
return s;
}
//询问区间和
int ask_sum(int u,int l,int r,int ql,int qr)
{
if(ql<=l && r<=qr) return sum[u];
pushdown(u);
int s = 0;
if(ql<=mid) s += ask_max(ls,l,mid,ql,qr);
if(mid+1<=qr) s += ask_max(rs,mid+1,r,ql,qr);
return s;
}
int ask_sum(int x,int y)
{
int s = 0;
while(top[x]!=top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
s += ask_sum(1,1,n,dfn[top[x]],dfn[x]);
x = f[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
if(x!=y)
s += ask_sum(1,1,n,dfn[x]+1,dfn[y]);
return s;
}
//询问时记得边的编号+1
#define print cout << "ok!\n" ;
int main()
{
ios::sync_with_stdio(false) , cin.tie(0);
cin>>n;
for(int i=1; i<n; i++)
{
int v,u,w; cin>>u>>v>>w , u++,v++;
e[u].push_back({v,w}) , e[v].push_back({u,w});
t[i] = {u,v};
}
dfs_1(1,0);
dfs_2(1,1);
build(1,1,n);
cin>>m;
for(int i=1; i<=m; i++)
{
string op; int u,v;
cin>>op>>u>>v;
/**/
if(op=="C") //单点修改
{
int g = dep[t[u].x] > dep[t[u].y]? t[u].x : t[u].y;
change_one(1,1,n,dfn[g],v);
}
else if(op=="N") //将区间取反
change(u+1,v+1);
else if(op=="SUM") //区间求和
cout << ask_sum(u+1,v+1) << '\n' ;
else if(op=="MAX") //区间最大
cout << ask_max(u+1,v+1) << '\n' ;
else if(op=="MIN") //区间最小
cout << ask_min(u+1,v+1) << '\n' ;
}
return 0;
}
回复
共 2 条回复,欢迎继续交流。
正在加载回复...