题目大意:

基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个城市,但是为了挣钱,他可能会去绕路。当然,由于工作室泛滥,所以一个城市的货物价格可能会发生改变。但是尊者神高达智商不足,他可能在一个很蠢的节点把货物卖掉,所以尊者神高达想知道每一次跑商最多能赔多少钱。

思路:

很容易想到答案为起点的值剪掉路径上最大值,然后问题就变成了求动态求路径最大值,如果是树的话直接树链剖分就好了,不是树的话就很难处理,我们机智的发现,一个环每条边都是可以走到的,所以我们可以用圆方树,方点为环上的最大值,然后发现好像维护不了,那我们改改定义,方点为儿子里面的最大值,这样如果lca是一个方点就还要特判断一下父亲节点。用平衡树来维护每个点的值。

程序:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<set>
using namespace std;
const int N=400005;
struct tree{int to,next;}e[N*2];
struct tree1{int to,next;}e1[N*2];
int n,n1,n2,cnt,p,m,q,cnt1;
int last[N],pr[N],f[N],pt[N],st[N],size[N],son[N],ft[2*N],mi[N],dfn[N],last1[N],low[N],dep[N*2],top[N*2];
int t[N*2][2];
multiset<int> h[N];
void add(int x,int y){e[++cnt].to=y; e[cnt].next=last[x]; last[x]=cnt;e[++cnt].to=x; e[cnt].next=last[y]; last[y]=cnt;
}void add1(int x,int y){e1[++cnt1].to=y; e1[cnt1].next=last1[x]; last1[x]=cnt1;e1[++cnt1].to=x; e1[cnt1].next=last1[y]; last1[y]=cnt1;
}void tarjan(int x,int fa){st[++st[0]]=x;low[x]=dfn[x]=++dfn[0];for(int i=last[x];i;i=e[i].next)if (e[i].to!=fa){if (!dfn[e[i].to]){tarjan(e[i].to,x);if (low[e[i].to]>=dfn[x]){add1(++n1,x); ;while (st[st[0]]!=e[i].to) add1(st[st[0]],n1),st[st[0]--]=0;add1(n1,e[i].to),st[st[0]--]=0;}else low[x]=min(low[x],low[e[i].to]);} else  low[x]=min(low[x],dfn[e[i].to]);}
}void dfs(int x,int fa){if (x<=n&&fa>n) h[fa].insert(pr[x]);dep[x]=dep[fa]+1;f[x]=fa;size[x]=1;for (int i=last1[x];i;i=e1[i].next)if (e1[i].to!=fa){dfs(e1[i].to,x);size[x]+=size[e1[i].to];if (size[e1[i].to]>size[son[x]]) son[x]=e1[i].to;  }
}void build(int x,int l,int r){mi[x]=1e9;if (l==r) pt[l]=x;else {int mid=(l+r)>>1;ft[t[x][0]=++n2]=x,build(n2,l,mid);ft[t[x][1]=++n2]=x,build(n2,mid+1,r);}
}void ins(int x,int v){mi[x]=v,x=ft[x];while (x) mi[x]=min(mi[t[x][0]],mi[t[x][1]]),x=ft[x];
}int query(int rt,int l,int r,int x,int y){if (!rt||x>y||x>r||y<l) return 1e9;if (x<=l&&r<=y) return mi[rt];int mid=(l+r)>>1;return min(query(t[rt][0],l,mid,x,y),query(t[rt][1],mid+1,r,x,y));
}void make(int x){if (!x) return;dfn[x]=++dfn[0];if (x>n) pr[x]=*h[x].begin();ins(pt[dfn[x]],pr[x]);top[son[x]]=top[x],make(son[x]);for (int i=last1[x];i;i=e1[i].next)if (e1[i].to!=f[x]&&e1[i].to!=son[x]){top[e1[i].to]=e1[i].to,make(e1[i].to);}
}int get(int x,int y){if (top[x]==top[y]){if (dep[x]>dep[y]) swap(x,y);int v=1e9;if (x>n) v=pr[f[x]];return min(v,query(1,1,n1,dfn[x],dfn[y]));}if (dep[top[x]]>dep[top[y]]) swap(x,y);return min(get(x,f[top[y]]),query(1,1,n1,dfn[top[y]],dfn[y]));
}int main(){freopen("a.in","r",stdin);freopen("a.out","w",stdout);
//  freopen("paoshang.in","r",stdin);
//  freopen("paoshang.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;i++) scanf("%d",&pr[i]);for (int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v);add(u,v);}n1=n;tarjan(1,0);dfs(1,0);n2=1;memset(dfn,0,sizeof(dfn));build(1,1,n1);make(1);scanf("%d",&q);for (int i=1;i<=q;i++){char ch;scanf("\n%c",&ch);int x,y;scanf("%d%d",&x,&y);if (ch=='Q') printf("%d\n",pr[x]-get(x,y));else{ins(pt[dfn[x]],y);if (x>1){int p=f[x];h[p].erase(h[p].find(pr[x]));h[p].insert(y);int v=*h[p].begin();if (v!=pr[p]){pr[p]=v;ins(pt[dfn[p]],pr[p]);}}pr[x]=y;}}
}

5909. 【NOIP2018模拟10.16】跑商(圆方树+树链剖分+SET)相关推荐

  1. [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)

    题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城 ...

  2. [JZOJ5909]【NOIP2018模拟10.16】跑商【圆方树】【树链剖分】

    Description 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从某个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个 ...

  3. jzoj5909 【NOIP2018模拟10.16】跑商(圆方树性质+树剖)

    Description 一个无向图,求从i到j简单路径(无重点)上的最小点权. n,m<=1e5 分析 考虑走到某个点双上时,假如不是同点进同点出,就可以获得这个点双上的所有贡献. 于是建出圆方 ...

  4. JZOJ 5909. 【NOIP2018模拟10.16】跑商(paoshang)

    Description 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖 ...

  5. JZOJ 5907. 【NOIP2018模拟10.16】轻功(qinggong)

    Description 题目背景: 尊者神高达进入了基三的世界,作为一个 mmorpg 做任务是必不可少的,然而跑地图却令人十分不爽.好在基三可以使用轻功,但是尊者神高达有些手残,他决定用梅花桩练习轻 ...

  6. jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)

    5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...

  7. jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)

    5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...

  8. jzoj5920. 【NOIP2018模拟10.21】风筝(dp,最长上升子序列)

    5920. [NOIP2018模拟10.21]风筝 Description 当一阵风吹来,风筝飞上天空,为了你,而祈祷,而祝福,而感动-- Description oyiya 在 AK 了 IOI 之 ...

  9. JZOJ 5898. 【NOIP2018模拟10.6】距离统计

    Description Input Output Sample Input 5 3 1 2 3 1 3 1 2 4 4 2 5 2 1 2 3 3 5 1 Sample Output 3 6 2 Da ...

最新文章

  1. java如何追加写入txt文件
  2. python创建一个类似于国家象棋棋盘的0-1矩阵_NumPy练习题(全中文并附详细讲解)...
  3. spring源码分析之spring-jdbc模块详解
  4. 2016/06/22 中色启动筹码分析作业
  5. 统计问题(HDU-2563)
  6. p1218 Superprime Rib
  7. 【预训练模型】预训练语言模型的前世今生之风起云涌
  8. unity中Rotation * Position的意义
  9. 2017-2018-1 20179202《Linux内核原理与分析》第四周作业
  10. 冒泡排序 BubbleSort
  11. 利用Python进行游戏脚本编程,不愧是最强的脚本语言!
  12. 浙大PAT 1063
  13. 软考常考知识点整理-项目人员配备管理计划
  14. VSCode 之 设置 settings.json 配置文件
  15. Windows 更新 升级 8007003错误 800tb109错误 文件没有正确签名 很难确定你的电脑能否运行win10【解决方法】
  16. 什么是虚拟机?虚拟机有那几种
  17. 台式计算机硬盘能扩大吗,电脑怎么增加磁盘内存
  18. 为什么去开发一个MLSQL
  19. 华为资深工程师:码农很多,但程序员并不多......
  20. 手把手教你做主成分分析

热门文章

  1. MySQL安装与配置心得体会_Mysql安装与配置总结
  2. QT应用隐藏启动外部应用
  3. php输出Resource id #3
  4. 安卓如何调出软键盘_Android开发中软键盘的显示和隐藏
  5. c++getline
  6. JavaScript 中如何判断变量是否为数字
  7. Runnable的使用
  8. 计算机运行的速度,如何让电脑运行更快(只需九招提升你的计算机运行速度)...
  9. 【51单片机】:关于51单片机仿真器(普中科技开发板STC89C51)的疑惑(做个记录)
  10. java数字转字符串的三种方式