题目内容:

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 旅行 模拟的更多相关文章

  1. 【JZOJ6419】模拟旅行&【BZOJ5506】【luoguP5304】旅行者

    description 某国有n座城市,这些城市之间通过m条单向道路相连,已知每条道路的长度. 不过,小X只对其中k座城市感兴趣. 为了更好地规划模拟旅行路线,提升模拟旅行的体验,小X想要知道他感兴趣 ...

  2. 【NOIP2015模拟11.5】JZOJ8月5日提高组T3 旅行

    [NOIP2015模拟11.5]JZOJ8月5日提高组T3 旅行 题目 若不存在第\(k\)短路径时,输出"Stupid Mike" 题解 题意 给出一个有\(n\)个点的树 问这 ...

  3. GDOI2014模拟 旅行【SPFA】

    旅行(travel) 从前有一位旅者,他想要游遍天下所有的景点.这一天他来到了一个神奇的王国:在这片土地上,有n个城市,从1到n进行编号.王国中有m条道路,第i条道路连接着两个城市ai,bi,由于年代 ...

  4. 2016级算法期末模拟练习赛-A.wuli51和京导的毕业旅行

    1063 wuli51和京导的毕业旅行 思路 中等题,二分+贪心. 简化题意,将m+1个数字分成n份,ans为这n段中每段数字和的最大值,求ans最小值及其方案. 对于这种求最小的最大值,最常用的方法 ...

  5. 【csp模拟赛4】旅行计划 (travelling.cpp)--欧拉回路

    [题目描述] 小 Z 打算趁着暑假,开启他的旅行计划.但与其他同学不同的是,小 Z 旅 行时并不关心到达了哪个网红景点打了哪些卡.小 Z 更关注沿路的风光,而且 小 Z 觉得,尽管多次到达同一个地方, ...

  6. csps模拟83最大异或和简单的括号序列旅行计划题解

    题面:https://www.cnblogs.com/Juve/articles/11733280.html 最大异或和: 简单博弈,小Q一定不会输,如果异或和为0,则平局,因为无论小Q如何拿,小T都 ...

  7. XJOI——NOIP2015提高组模拟题19-day1——观光旅行

    http://www.hzxjhs.com:83/contest/493/problem/3 [题目大意] 给定一个有n(n<=500000)个点,m(1<=500000)条边的无向图.给 ...

  8. 校内模拟赛 旅行(by NiroBC)

    题意: n个点的无向图,Q次操作,每次操作可以连接增加一条边,询问两个点之间有多少条边是必经之路.如果不连通,输出-1. 分析: 首先并查集维护连通性,每次加入一条边后,如果这条边将会连接两个联通块, ...

  9. noip模拟赛 旅行

    分析:一个贪心的想法是每次找到根的点权和最大的点进行操作,关键是怎么维护.每次找最大值,修改后会对这条链上每个点的子树上的点造成影响,可以用线段树来维护.找最大值就是区间求最大值嘛,对子树进行操作利用 ...

随机推荐

  1. JavaScript中的函数使用

    append() 是代表改变格子的内容 prev()是代表前一个格子 next()是代表下一个相邻的格子 hide()是代表隐藏 show()是代表显示 childen()是代表子节点 eq()是代表 ...

  2. SpringMVC-HelloWorld (XML)

    Spring2.5.6开启了Spring的注解时代,简化了的xml配置,提高了开发效率:但是,对于Spring的初学者,xml配置更容易理解的Spring的Ioc特性,aop特性:本文使用Maven构 ...

  3. spring init

    DN学院讲师招募     Markdown编辑器轻松写博文     TOP 50 CTO坐镇直招     读文章说感想获好礼 通过Spring @PostConstruct 和 @PreDestroy ...

  4. mysql数据库的中文乱码问题的解决

    今天终于解决了数据库中文乱码的问题,分享出来让更多的人作为参考,我们进入主题: 如果在搭建mysql数据库的时候没有设置它的编码格式,在以后的开发中,中文乱码会是一个令人头疼的问题,所以我在这里分享一 ...

  5. mybatis基础,mybatis配置文件核心组件typeHandler元素

    无论是从预处理语句中设置一个值,还是从结果集里取出一个值,都会用类型处理器将获取的值以合适的方式转换成 Java 类型 可以重写类型处理器或创建你自己的类型处理器来处理不支持的或非标准的类型 实现 o ...

  6. linux 私房菜 CH7 Linux 档案与目录管理

    路径 ``` . 此层目录 .. 上一级目录 前一个工作目录 ~ 当前用户的家的目录 ``` 变换目录 cd 显示目录 pwd [-P] -P 显示出确实的路径,而非使用链接 (link) 路径. 创 ...

  7. react router路径的匹配原则

    路由匹配规则是从上到下执行,一旦发现匹配,就不再其余的规则了. (1):paramName :paramName匹配URL的一个部分,直到遇到下一个/.?.#为止.这个路径参数可以通过this.pro ...

  8. 对象作为 map 的 key 时,需要重写 equals 方法和 hashCode 方法

    对象作为 map 的 key 时,需要重写 hashCode 和 equals方法 如果没有重写 hashCode 方法,那么下面的代码示例会输出 null 我们首先定义一个对象:BmapPoint, ...

  9. C++STL的简单使用

    #include <iostream>#include <vector>#include<deque>#include <list>#include&l ...

  10. (4)Object对象的几个常用方法

    Object对象是java中对象的始祖,其有一些方法是经常需要我们来改写的: toString方法 该方法是Object的方法,Object的这的方法返回的是对象的文件结构加上对象的hashcode, ...