5909. 【NOIP2018模拟10.16】跑商(圆方树+树链剖分+SET)
题目大意:
基三的地图可以看做 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)相关推荐
- [JZOJ 5909] [NOIP2018模拟10.16] 跑商(paoshang) 解题报告 (圆方树)
题目链接: https://jzoj.net/senior/#contest/show/2529/2 题目: 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城 ...
- [JZOJ5909]【NOIP2018模拟10.16】跑商【圆方树】【树链剖分】
Description 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从某个点出发并在起点购买货物,在旅途中任意一点卖出并最终到达终点,尊者神高达的时间很宝贵,所以他不会重复经过同一个 ...
- jzoj5909 【NOIP2018模拟10.16】跑商(圆方树性质+树剖)
Description 一个无向图,求从i到j简单路径(无重点)上的最小点权. n,m<=1e5 分析 考虑走到某个点双上时,假如不是同点进同点出,就可以获得这个点双上的所有贡献. 于是建出圆方 ...
- JZOJ 5909. 【NOIP2018模拟10.16】跑商(paoshang)
Description 题目背景: 尊者神高达很穷,所以他需要跑商来赚钱 题目描述: 基三的地图可以看做 n 个城市,m 条边的无向图,尊者神高达会从任意一个点出发并在起点购买货物,在旅途中任意一点卖 ...
- JZOJ 5907. 【NOIP2018模拟10.16】轻功(qinggong)
Description 题目背景: 尊者神高达进入了基三的世界,作为一个 mmorpg 做任务是必不可少的,然而跑地图却令人十分不爽.好在基三可以使用轻功,但是尊者神高达有些手残,他决定用梅花桩练习轻 ...
- jzoj5904. 【NOIP2018模拟10.15】刺客信条(并查集)
5904. [NOIP2018模拟10.15]刺客信条 Description 故事发生在1486 年的意大利,Ezio 原本只是一个文艺复兴时期的贵族,后来因为家族成员受到圣殿骑士的杀害,决心成为一 ...
- jzoj 5906. 【NOIP2018模拟10.15】传送门(树形dp)
5906. [NOIP2018模拟10.15]传送门 Description 8102年,Normalgod在GLaDOS的帮助下,研制出了传送枪.但GLaDOS想把传送枪据为己有,于是把Normal ...
- jzoj5920. 【NOIP2018模拟10.21】风筝(dp,最长上升子序列)
5920. [NOIP2018模拟10.21]风筝 Description 当一阵风吹来,风筝飞上天空,为了你,而祈祷,而祝福,而感动-- Description oyiya 在 AK 了 IOI 之 ...
- 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 ...
最新文章
- java如何追加写入txt文件
- python创建一个类似于国家象棋棋盘的0-1矩阵_NumPy练习题(全中文并附详细讲解)...
- spring源码分析之spring-jdbc模块详解
- 2016/06/22 中色启动筹码分析作业
- 统计问题(HDU-2563)
- p1218 Superprime Rib
- 【预训练模型】预训练语言模型的前世今生之风起云涌
- unity中Rotation * Position的意义
- 2017-2018-1 20179202《Linux内核原理与分析》第四周作业
- 冒泡排序 BubbleSort
- 利用Python进行游戏脚本编程,不愧是最强的脚本语言!
- 浙大PAT 1063
- 软考常考知识点整理-项目人员配备管理计划
- VSCode 之 设置 settings.json 配置文件
- Windows 更新 升级 8007003错误 800tb109错误 文件没有正确签名 很难确定你的电脑能否运行win10【解决方法】
- 什么是虚拟机?虚拟机有那几种
- 台式计算机硬盘能扩大吗,电脑怎么增加磁盘内存
- 为什么去开发一个MLSQL
- 华为资深工程师:码农很多,但程序员并不多......
- 手把手教你做主成分分析