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模拟赛 旅行
分析:一个贪心的想法是每次找到根的点权和最大的点进行操作,关键是怎么维护.每次找最大值,修改后会对这条链上每个点的子树上的点造成影响,可以用线段树来维护.找最大值就是区间求最大值嘛,对子树进行操作利用 ...
随机推荐
- fir.im Weekly - 8 个不能错过的 iOS / Android 技术分享
本期 fir.im Weekly 收集了 2 月下旬新鲜出炉的 iOS /Android 技术分享.源码等,iOS 中图片技术的解压缩.逆向实战.iOS SDK 实践,Android架构思考.Andr ...
- 【转】svn cleanup failed–previous operation has not finished; run cleanup if it was interrupted
svn提交遇到恶心的问题,可能是因为上次cleanup中断后,进入死循环了. 错误如下 解决方法:清空svn的队列 1.下载sqlite3.exe 2.找到你项目的.svn文件,查看是否存在wc.db ...
- Foundation Kit介绍
Cocoa实际上是由许多个不同的框架组成的,其中最常用于桌面端(OS X)应用程序的是Foundation和Application Kit.它包含了所有的用户界面对象和高级类.如果打算开发ios平台上 ...
- 【2017-02-21】分支语句if...else...、分支嵌套、变量的作用域
语句是指程序命令,都是按照顺序执行的. 语句又分为: 顺序语句:从上到下按顺序执行,挨个执行一遍. 分支语句:选择性执行语句,有的可能会执行,有的可能不执行.满足条件执行. 循环语句: 一.分支语句 ...
- Maven 搭建SpringMvc+Spring+Mybatis详细记录
总觉得,看比人写的总是那么好,每次搭建框架时都会找博客,找教程来跟着一步一步走,虽然很快搭建成功了,但是经常情况是我并不知道我干了什么,也不记得具体步骤,到底为什么要这么做,今天我详细记录了一下自己搭 ...
- ajax 写登录
AJAX的全称是Asynchronous JavaScript and XML(异步的 JavaScript 和 XML). ajax的优点: 1.最大的一点是页面无刷新,用户的体验非常好. 2.使用 ...
- Spark性能调优之代码方面的优化
Spark性能调优之代码方面的优化 1.避免创建重复的RDD 对性能没有问题,但会造成代码混乱 2.尽可能复用同一个RDD,减少产生RDD的个数 3.对多次使用的RDD进行持久化(ca ...
- SQL server 数据库 ——聚合函数(一列 多行,值类型)
聚合函数 5种函数: 1.max最大值 select max(price) from car where code='c024' 2.min最小值 select * from car wher ...
- 1441: Min
1441: Min Time Limit: 5 Sec Memory Limit: 64 MBSubmit: 320 Solved: 213[Submit][Status][Discuss] De ...
- [ZooKeeper.net] 3 ZooKeeper的分布式锁
基于ZooKeeper的分布式锁 ZooKeeper 里实现分布式锁的基本逻辑: 1.zookeeper中创建一个根节点(Locks),用于后续各个客户端的锁操作. 2.想要获取锁的client都在L ...