BZOJ2157 旅行 模拟
题目内容:
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
题目分析:
一道码农题,最难的地方在于如何判断输入的是哪个操作,所以要深刻掌握switch,下面我来讲讲switch的用法。
switch的主要结构是:
switch(a){
case x:{......;break;}
case y:{......;break;}
default:{.......}
}
值得注意的是case可以写任意多个且不能像if那样进行大于小于等的比较,所以switch的用处没有if大,而且switch可以完全用if代替,但是switch可以更方便地判断数字是否是这个并且作出操作。考虑到编程习惯,所以switch中case后面的括号是可以省略的。
题目代码:
#include<bits/stdc++.h>
#define SUM t[now].sum
#define MIN t[now].minn
#define MAX t[now].maxx
using namespace std;
struct edge{
int to,w;
};
const int INF = ;
const int maxn = ;
vector <edge> g[maxn];
int d[maxn],arr[maxn],fa[maxn],son[maxn],head[maxn],sz[maxn],num[maxn],dep[maxn];
int to_fa[maxn],fto_fa[maxn];
struct ed{int from,to;};
vector <ed> edges;
void dfs1(int now,int f,int d){
arr[now] = ;
dep[now] = d;
fa[now] = f;
sz[now] = ;
int maxx = ;
for(int i=;i<g[now].size();i++){
if(arr[g[now][i].to]){
to_fa[now] = i;
continue;
}
fto_fa[g[now][i].to] = i;
dfs1(g[now][i].to,now,d+);
sz[now] += sz[g[now][i].to];
if(sz[g[now][i].to] > maxx){
maxx = sz[g[now][i].to];
son[now] = g[now][i].to;
}
}
} int a[];
int bh = ; void dfs2(int now,int h){
arr[now] = ;
head[now] = h;
for(int i=;i<g[now].size();i++){
if(g[now][i].to == son[now]&&!arr[g[now][i].to]){
num[now] = ++bh;
a[bh] = g[now][i].w;
dfs2(g[now][i].to,h);
break;
}
}
for(int i=;i<g[now].size();i++){
if(g[now][i].to != son[now] && arr[g[now][i].to]==){
dfs2(g[now][i].to,g[now][i].to);
}
}
}
struct node{
int sum,minn,maxx;
int f;
}t[];
void push_down(int);
void push_up(int now){
if(t[now].f)push_down(now);
if(t[now * ].f) push_down(now*);
if(t[now*+].f)push_down(now*+);
SUM = t[now * ].sum + t[now * + ].sum;
MIN = min(t[now * ].minn,t[now*+].minn);
MAX = max(t[now*].maxx,t[now*+].maxx);
} void build_tree(int l,int r,int now){
if(l == r){
SUM = MAX = MIN = a[l];
return;
}
int mid = (l+r) >> ;
build_tree(l,mid,now * );
build_tree(mid+,r,now * + );
push_up(now);
} void push_down(int now){
SUM = -SUM;
swap(MIN,MAX);
MIN = -MIN;
MAX = -MAX;
t[now * ].f ^= ;
t[now * + ].f ^=;
t[now].f = ;
} struct ask{
int u,v,dir;
}A[];
int pre[];
struct point{
int dis,num;
};
vector <point> lca[];
int get_l[];
int found(int x){
int rx = x;
while(pre[rx]!=rx)rx = pre[rx];
while(pre[x]!=rx){
int temp = pre[x];
pre[x] = rx;
x = temp;
}
return rx;
}
void tarjan(int now,int fa){
arr[now] = ;
for(int i=;i<lca[now].size();i++){
if(arr[lca[now][i].dis]){
get_l[lca[now][i].num] = found(lca[now][i].dis);
}
}
for(int i=;i<g[now].size();i++){
if(arr[g[now][i].to]) continue;
tarjan(g[now][i].to,now);
}
pre[found(now)] = found(fa);
} void change(int l,int r,int c,int delta,int now){
if(t[now].f) push_down(now);
if(l == c && r == c){
SUM = delta;
MIN = delta;
MAX = delta;
return;
}
int mid = (l+r) >> ;
if(c <= mid)change(l,mid,c,delta,now * );
else change(mid+,r,c,delta,now * + );
push_up(now);
}
void opp(int l,int r,int begin,int end,int now){//[l,r]树,[begin,end]询问
if(t[now].f) push_down(now);
if(begin>r||end<l||begin>end)return;
if(l>=begin&&r<=end){
t[now].f ^=;
if(t[now].f)push_down(now);
return;
}
int mid = (l + r) >> ;
opp(l,mid,begin,end,now*);
opp(mid+,r,begin,end,now*+);
push_up(now);
} struct stru{int sum,max,min;}; stru merge(stru a,stru b){
stru c = (stru){a.sum+b.sum,max(a.max,b.max),min(a.min,b.min)};
return c;
} stru get_sum(int l,int r,int begin,int end,int now){
if(t[now].f) push_down(now);
if(begin > r || end < l||begin>end) return (stru){,-INT_MAX,INT_MAX};
if(l >= begin && r <= end){
return (stru){SUM,MAX,MIN};
}
int mid = (l+r) >> ;
stru ans = get_sum(l,mid,begin,end,now * );
ans = merge(ans,get_sum(mid+,r,begin,end,now*+));
push_up(now);
return ans;
} int main(){
ios::sync_with_stdio(false);
int n; cin >> n;
edges.push_back((ed){,});
for(int i=;i<n;i++){
int x,y,w;
cin >> x >> y >> w;
x++;y++;
edges.push_back((ed){x,y});
g[x].push_back((edge){y,w});
g[y].push_back((edge){x,w});
}
dfs1(,-,);
memset(arr,,sizeof(arr));
dfs2(,);
build_tree(,bh,);
int m;cin >> m;
for(int i=;i<=m;i++){
string str; cin >> str;
if(str[] == 'C') A[i].dir = ;
if(str[] == 'N') A[i].dir = ;
if(str[] == 'S') A[i].dir = ;
if(str[] == 'A') A[i].dir = ;
if(str[] == 'I') A[i].dir = ;
int u,v; cin >> u >> v;
if(A[i].dir!=)u++,v++;
A[i].u = u;
A[i].v = v;
if(A[i].dir == ) continue;
lca[u].push_back((point){v,i});
lca[v].push_back((point){u,i});
}
memset(arr,,sizeof(arr));
for(int i=;i<=n;i++) pre[i] = i;
tarjan(,-);
for(int i=;i<=m;i++){
if(A[i].dir == ){
int u = edges[A[i].u].from;
int v = edges[A[i].u].to;
if(fa[v] != u) swap(u,v);
if(son[u] == v){
int h = head[v];
int bg = num[h];
int ch = dep[u]-dep[h];
bg = bg + ch;
change(,bh,bg,A[i].v,);
}else{
int e = to_fa[v];
int ne = fto_fa[v];
g[u][ne].w = A[i].v;
g[v][e].w = A[i].v;
}
continue;
}
int lac = get_l[i];
int s = A[i].u,t = A[i].v;
if(dep[s]<=dep[t])swap(s,t);
if(A[i].dir == ){
while(s!=lac && dep[s] > dep[lac]){
int h = head[s];
if(h == s){
int e = to_fa[s];
int ne = fto_fa[s];
g[fa[s]][ne].w = -g[fa[s]][ne].w;
g[s][e].w = -g[s][e].w;
s = fa[s];
continue;
}
int bg = num[h];
if(dep[h] >= dep[lac]){
int ch = dep[s]-dep[h]-;
int end = bg + ch;
opp(,bh,bg,end,);
s = h;
}else{
bg = num[lac];
int ch = dep[s]-dep[lac]-;
int end = bg + ch;
opp(,bh,bg,end,);
s = lac;
break;
}
}
while(t!=lac&&dep[t] > dep[lac]){
int h = head[t];
if(h == t){
int e = to_fa[t];
int ne = fto_fa[t];
g[fa[t]][ne].w = -g[fa[t]][ne].w;
g[t][e].w = -g[t][e].w;
t = fa[t];
continue;
}
int bg = num[h];
if(dep[h] > dep[lac]){
int ch = dep[t]-dep[h]-;
int end = bg + ch;
opp(,bh,bg,end,);
t = h;
}else{
bg = num[lac];
int ch = dep[t]-dep[lac]-;
int end = bg+ch;
opp(,bh,bg,end,);
break;
}
}
continue;
}
int &pd = A[i].dir;
if(pd == ||pd == ||pd == ){
int ans = ;
if(pd == ) ans = INT_MAX;
if(pd == ) ans = -INT_MAX;
while(s!=lac&&dep[s] > dep[lac]){
int h = head[s];
if(h == s){
int e = to_fa[s];
if(pd == ) ans += g[s][e].w;
else if(pd == ) ans = max(ans,g[s][e].w);
else ans = min(ans,g[s][e].w);
s = fa[s];
continue;
}
int bg = num[h];
if(dep[h] >= dep[lac]){
int ch = dep[s] - dep[h] - ;
int end = bg + ch;
stru p = get_sum(,bh,bg,end,);
if(pd == ) ans += p.sum;
else if(pd == ) ans = max(ans,p.max);
else ans = min(ans,p.min);
s = h;
}else{
bg = num[lac];
int ch = dep[s] - dep[lac] - ;
int end = bg + ch;
stru p = get_sum(,bh,bg,end,);
if(pd == ) ans += p.sum;
else if(pd == ) ans = max(ans,p.max);
else ans = min(ans,p.min);
s = lac;
break;
}
}
while(t!=lac&&dep[t] > dep[lac]){
int h = head[t];
if(h == t){
int e = to_fa[t];
if(pd == ) ans += g[t][e].w;
else if(pd == ) ans = max(ans,g[t][e].w);
else ans = min(ans,g[t][e].w);
t = fa[t];
continue;
}
int bg = num[h];
if(dep[h] > dep[lac]){
int ch = dep[t] - dep[h] - ;
int end = bg + ch;
stru p = get_sum(,bh,bg,end,);
if(pd == ) ans += p.sum;
else if(pd == ) ans = max(ans,p.max);
else ans = min(ans,p.min);
t = h;
}else{
bg = num[lac];
int ch = dep[t] - dep[lac] - ;
int end = bg + ch;
stru p = get_sum(,bh,bg,end,);
if(pd == ) ans += p.sum;
else if(pd == ) ans = max(ans,p.max);
else ans = min(ans,p.min);
break;
}
}
printf("%d\n",ans);
}
}
return ;
}
BZOJ2157 旅行 模拟的更多相关文章
- 【JZOJ6419】模拟旅行&【BZOJ5506】【luoguP5304】旅行者
description 某国有n座城市,这些城市之间通过m条单向道路相连,已知每条道路的长度. 不过,小X只对其中k座城市感兴趣. 为了更好地规划模拟旅行路线,提升模拟旅行的体验,小X想要知道他感兴趣 ...
- 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行
[NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...
- GDOI2014模拟 旅行【SPFA】
旅行(travel) 从前有一位旅者,他想要游遍天下所有的景点.这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号.王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年代 ...
- 2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行
1063 wuli51和京导的毕业旅行 思路 中等题,二分+贪心. 简化题意,将m+1个数字分成n份,ans为这n段中每段数字和的最大值,求ans最小值及其方案. 对于这种求最小的最大值,最常用的方法 ...
- 【csp模拟赛4】旅行计划 (travelling.cpp)--欧拉回路
[题目描述] 小 Z 打算趁着暑假,开启他的旅行计划.但与其他同学不同的是,小 Z 旅 行时并不关心到达了哪个网红景点打了哪些卡.小 Z 更关注沿路的风光,而且 小 Z 觉得,尽管多次到达同一个地方, ...
- csps模拟83最大异或和简单的括号序列旅行计划题解
题面:https://www.cnblogs.com/Juve/articles/11733280.html 最大异或和: 简单博弈,小Q一定不会输,如果异或和为0,则平局,因为无论小Q如何拿,小T都 ...
- XJOI——NOIP2015提高组模拟题19-day1——观光旅行
http://www.hzxjhs.com:83/contest/493/problem/3 [题目大意] 给定一个有n(n<=500000)个点,m(1<=500000)条边的无向图.给 ...
- 校内模拟赛 旅行(by NiroBC)
题意: n个点的无向图,Q次操作,每次操作可以连接增加一条边,询问两个点之间有多少条边是必经之路.如果不连通,输出-1. 分析: 首先并查集维护连通性,每次加入一条边后,如果这条边将会连接两个联通块, ...
- noip模拟赛 旅行
分析:一个贪心的想法是每次找到根的点权和最大的点进行操作,关键是怎么维护.每次找最大值,修改后会对这条链上每个点的子树上的点造成影响,可以用线段树来维护.找最大值就是区间求最大值嘛,对子树进行操作利用 ...
随机推荐
- 阿里云服务器 发送邮箱 STMP 25端口 465端口问题 Javamail 25被禁用
我们传统使用的比较简单的是 STMP 25端口收发邮件 今天发现刚购买的阿里云服务器不能作为客户端通过STMP 25端口发送邮件 开始在网上有说发现是JDK1.8的原因,然后自己也把JDK1.8换到了 ...
- hibernate系列笔记(2)---Hibernate的核心API
Hibernate的核心API 一般我们通过hibernate进行操作的时候,都会遵循下面的流程,那么接下来我对每一个步骤进行讲解: 1 public void testInsert() { 2 // ...
- (三目运算符)PHP中问号?和冒号: 的作用
<表达式1>?<表达式2>:<表达式3>; "?"运算符的含义是: 先求表达式1的值, 如果为真, 则执行表达式2,并返回表达式2的结果 ; 如 ...
- JS中的onclick事件
原文链接:https://segmentfault.com/q/1010000007955542?_ea=1503986 我自己做了一下测试. 这个是在html里面直接绑定onclick事件,我打印了 ...
- Vmware虚拟机设置静态IP地址
一.安装好虚拟后在菜单栏选择编辑→ 虚拟网络编辑器,打开虚拟网络编辑器对话框,选择Vmnet8 Net网络连接方式,随意设置子网IP,点击NAT设置页面,查看子网掩码和网关,后面修改静态IP会用到. ...
- 转换器3:手写PHP转Python编译器,词法部分
上周写了<ThinkPhp模板转Flask.Django模板> 一时技痒,自然而然地想搞个大家伙,把整个PHP程序转成Python.不比模板,可以用正则匹配偷懒,这次非写一个Php编译器不 ...
- wemall app商城源码中ScrollView中嵌套ListView主要代码
很多时间我们在scorllview中嵌入listview的时候,都只能看到listview显示一行数据,而我们的要求是显示多行,即我们数据的行数, 当ListView的高度设定一定的值时,ListVi ...
- 1297: [SCOI2009]迷路
1297: [SCOI2009]迷路 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 652 Solved: 442[Submit][Status] ...
- 1588: [HNOI2002]营业额统计
1588: [HNOI2002]营业额统计 Time Limit: 5 Sec Memory Limit: 162 MBSubmit: 9203 Solved: 3097[Submit][Stat ...
- ReactJS React+Redux+Router+antDesign通用高效率开发模板,夜间模式为例
工作比较忙,一直没有时间总结下最近学习的一些东西,为了方便前端开发,我使用React+Redux+Router+antDesign总结了一个通用的模板,这个技术栈在前端开发者中是非常常见的. 总的来说 ...