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模拟赛 旅行
分析:一个贪心的想法是每次找到根的点权和最大的点进行操作,关键是怎么维护.每次找最大值,修改后会对这条链上每个点的子树上的点造成影响,可以用线段树来维护.找最大值就是区间求最大值嘛,对子树进行操作利用 ...
随机推荐
- video.js支持m3u8格式直播
为什么要使用video.js? 1. PC端浏览器并不支持video直接播放m3u8格式的视频 2. 手机端各式各样的浏览器定制的video界面风格不统一,直接写原生的js控制视频兼容性较差 3. v ...
- centos7搭建nexus maven私服
前置条件: 1.安装jdk,可参考 http://www.cnblogs.com/grey-wolf/p/6480489.html 2.nexus仓库管理器,分为两个版本,Nexus Reposito ...
- ES6-01:常量与变量的声明
首先,我们声明一个变量: //定义一个变量num,并赋值为10: let num = 10; //进行打印 console.log(num); let与var有所不同: 语法特点1:let变量只能在当 ...
- js获取浏览器宽高
IE中: document.body.clientWidth ==> BODY对象宽度 document.body.clientHeight ==> BODY对象高度 document.d ...
- solr6.4.1搜索引擎同步mysql数据库
尚未成功启动solr的,请参考我的另一篇文章:http://www.cnblogs.com/zhuwenjoyce/p/6506359.html(solr6.4.1 搜索引擎启动eclipse启动) ...
- 如何让celery接受定制的参数
背景介绍 最近的一个项目使用到celery结算订单,使用celery的确很方便.但是复杂的内部框架导致了需要传人大量的参数例如数据库配置文件等.下面先来看看我仿照官网写的代码.所有代码都放到githu ...
- 香港多IP站群服务器-搭建多IP代理服务器、游戏加速服务器
耀磊花楹qq82521463香港WK自营机房多IP服务器租用,多IP站群服务器,多IP多C段 站群服务器租用 耀磊数据拥有3万个自由香港IP以及独立AS号,是APNIC核心成员,机房通过BGP融合 多 ...
- ThinkPhp框架:有条件的数据库查询、tp框架的其他知识
上一篇的随笔写的是基本操作,现在可以做一些高级操作,例如有条件的查询数据,有分页的条件查询数据 一.一个条件的查询数据 查询数据自然是先要显示出数据,然后根据条件进行查询数据 (1)显示出表的数据 这 ...
- USACO全部月赛及GateWay数据
月赛: 以07年open为例,网站如下 http://contest.usaco.org/OPEN07 其他的格式是http://contest.usaco.org/月份(月份的英文前三位,比如1月是 ...
- Java 中的锁——Lock接口
Java SE5之后,并发包中新增了Lock接口(以及相关实现类)用来实现锁功能.虽然它少了(通过synchronized块或者方法所提供的)隐式获取释放锁的便捷性,但是却拥有了锁获取与释放的操作性. ...