倍增什么的最慢了,常数太大了

我们可以上树剖啊

但是如果用树剖来查询树上两点之间的最小边权的话,可能只能在上一棵线段树?

那也太\(naive\)了,尽管倍增常数大,但是还是比两个\(log\)快的

那干脆重构树算了

我们直接建出\(kruskal\)重构树,之后我们可以在重构树上直接用树剖来查询\(lca\),\(lca\)的点权就是最小边的边权

这就是我最优解的原因了

之后发现自己的思路非常清奇,那就干脆再写一下思路吧

可能是我太傻了,并没有发现可以直接贪心,所以搞出来一种非常难写的方法

我们定义一个\(Maxn\)数组,\(Maxn[i]\)表示\(i\)次交易后最多可以携带多少枚金子

显然\(Maxn[n]=0\),\(n\)次交易后我们不能再有金子了

之后我们倒着推出\(Maxn\)数组

首先\(Maxn[i]\)应该等于\(i\)次交易和\(i+1\)次交易之间两点的最小边权

如果\(a[i+1]<0\),我们可以通过卖出消耗掉一些,那就说明我们可以多往后传递一些,于是就有\(Maxn[i]-|a[i+1]|<=Maxn[i+1]\)

也就是\(Maxn[i]<=Maxn[i]-a[i+1]\)

如果\(a[i+1]>0\),我们卖出都不能了,于是就有\(Maxn[i]<=Maxn[i+1]\)

求出\(Maxn\)数组之后贪心就可以啦

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<iostream>
#define re register
#define maxn 100005
#define INF 9999999999
#define LL long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
struct E
{
int v,nxt;
}e[maxn<<2];
struct g
{
int x,y;
LL z;
}G[maxn<<1];
int fa[maxn<<1];
int sum[maxn<<1],Fa[maxn<<1],top[maxn<<1],deep[maxn<<1],son[maxn<<1],head[maxn<<1];
int n,m,q,num;
LL Maxn[maxn];
int c[maxn<<1];
LL a[maxn],b[maxn];
LL val[maxn<<2];
inline LL read()
{
char c=getchar();
LL x=0,r=1;
while(c<'0'||c>'9') {if(c=='-') r=-1;c=getchar();}
while(c>='0'&&c<='9')
x=(x<<3)+(x<<1)+c-48,c=getchar();
return x*r;
}
inline int find(int x)
{
if(x==fa[x]) return x;
return fa[x]=find(fa[x]);
}
inline void add_edge(int x,int y)
{
e[++num].v=y;
e[num].nxt=head[x];
head[x]=num;
}
void dfs1(int x)
{
sum[x]=1;
int maxx=-1;
for(re int i=head[x];i;i=e[i].nxt)
if(!deep[e[i].v])
{
deep[e[i].v]=deep[x]+1;
Fa[e[i].v]=x;
dfs1(e[i].v);
sum[x]+=sum[e[i].v];
if(sum[e[i].v]>maxx) maxx=sum[e[i].v],son[x]=e[i].v;
}
}
void dfs2(int x,int topf)
{
top[x]=topf;
if(!son[x]) return;
dfs2(son[x],topf);
for(re int i=head[x];i;i=e[i].nxt)
if(deep[e[i].v]>deep[x]&&son[x]!=e[i].v) dfs2(e[i].v,e[i].v);
}
inline int LCA(int x,int y)
{
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]]) std::swap(x,y);
x=Fa[top[x]];
}
if(deep[x]<deep[y]) return x;
return y;
}
inline int cmp(g a,g b)
{
return a.z>b.z;
}
signed main()
{
n=read(),m=read(),q=read();
for(re int i=1;i<=n;i++) b[i]=read();
for(re int i=1;i<=n;i++) a[i]=read();
for(re int i=1;i<=m;i++)
G[i].x=read(),G[i].y=read(),G[i].z=read();
for(re int i=1;i<=n*2;i++) c[i]=i;
if(q>=1)
{
int pre=read(),X;
for(re int i=1;i<q;i++)
{
X=read();
c[X]=pre;
}
}
std::sort(G+1,G+m+1,cmp);
for(re int i=1;i<=n*2;i++)
if(c[i]==i) fa[i]=i;
int cnt=n;
for(re int i=1;i<=m;i++)
{
int xx=find(c[G[i].x]);
int yy=find(c[G[i].y]);
if(xx==yy) continue;
add_edge(++cnt,xx),add_edge(cnt,yy);
add_edge(xx,cnt),add_edge(yy,cnt);
val[cnt]=G[i].z;
fa[xx]=cnt,fa[yy]=cnt;
}
deep[cnt]=1;
dfs1(cnt);
dfs2(cnt,cnt);
Maxn[n]=0;
for(re int i=n-1;i;i--)
{
int lca=LCA(c[b[i]],c[b[i+1]]);
Maxn[i]=val[lca];
if(lca==c[b[i]]) Maxn[i]=INF;
if(a[b[i+1]]<0)
Maxn[i]=min(Maxn[i+1]-a[b[i+1]],Maxn[i]);
else
Maxn[i]=min(Maxn[i],Maxn[i+1]);
}
LL now=0;
for(re int i=1;i<=n;i++)
{
if(a[b[i]]>0) now=min(Maxn[i],a[b[i]]+now);
else
{
printf("%lld\n",min(now,-a[b[i]]));
now+=a[b[i]];
now=max(now,0);
}
}
return 0;
}

【[SCOI2013]摩托车交易 】的更多相关文章

  1. BZOJ3322[Scoi2013]摩托车交易——最大生成树+贪心+倍增

    题目描述 mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意.在mzry1992 生活的地方,城市之间是用双向高速公路连接的.另外,每条高速公路有一个载重上限,即在不 ...

  2. BZOJ3322 : [Scoi2013]摩托车交易

    求出最大生成树,则两点间的最大容量为树上两点间的边权的最小值. 设$lim[i]$表示第$i$个订单的城市允许携带的黄金上限,则 $lim[i]=\min(lim[i+1],a[i]和a[i+1]点间 ...

  3. 2019.03.28 bzoj3322: [Scoi2013]摩托车交易(kruskal重构树+贪心)

    传送门 题意咕咕咕 思路: 先把所有可以列车通的缩成一个点,然后用新图建立kruskalkruskalkruskal重构树. 这样就可以倒着贪心模拟了. 代码: #include<bits/st ...

  4. [SCOI2013]摩托车交易 kruskal重构树(最大生成树) 倍增

    ---题面--- 题解: 这题想法简单,,,写起来真的是失智,找了几个小时的错误结果是inf没开到LL范围.... 首先我们需要找到任意两点之间能够携带黄金的上限值,因为是在经过的道路权值中取min, ...

  5. [SCOI2013]摩托车交易 题解

    思路分析 为了让交易额尽量大,显然我们需要尽量多地买入.对于每个城市,到达这个城市时携带的黄金受到几个条件的影响:之前卖出的黄金,之前能买入的最多的黄金,前一个城市到当前城市的路径上的最小边权.既然不 ...

  6. 【SCOI2013】摩托车交易 - 最大生成树+树链剖分

    题目描述 mzry1992 在打完吊针出院之后,买了辆新摩托车,开始了在周边城市的黄金运送生意.在mzry1992 生活的地方,城市之间是用双向高速公路连接的.另外,每条高速公路有一个载重上限,即在不 ...

  7. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  8. BZOJ3323: [Scoi2013]多项式的运算

    3323: [Scoi2013]多项式的运算 Time Limit: 12 Sec  Memory Limit: 64 MBSubmit: 128  Solved: 33[Submit][Status ...

  9. 高频交易算法研发心得--MACD指标算法及应用

    凤鸾宝帐景非常,尽是泥金巧样妆. 曲曲远山飞翠色:翩翩舞袖映霞裳. 梨花带雨争娇艳:芍药笼烟骋媚妆. 但得妖娆能举动,取回长乐侍君王. [摘自<封神演义>纣王在女娲宫上香时题的诗] 一首定 ...

随机推荐

  1. c#项目代码风格要求

    代码风格没有正确与否,重要的是整齐划一,这是我拟的一份<.Net 项目代码风格要求>,供大家参考. 1. C# 代码风格要求 1.1注释 类型.属性.事件.方法.方法参数,根据需要添加注释 ...

  2. Java - 将可变性最小化

    不可变类,即实例不能被修改的类,实例中包含的所有信息在对象的生命周期内固定不变. 常见的比如String.基本类型的封装类.BigDecimal.BigInteger. 相对与可变类,不可变更易于设计 ...

  3. 你所需要的sql数据库资料

     sql语法的特点  1.没有"",所有的字符串都使用''包含  2.它的逻辑相等与赋值运算符一样都是= 如 if 1=1  3.不区别大小写,但是习惯函数上使用大写.所有与数据库 ...

  4. [javaSE] 数据结构(AVL树基本概念)

    AVL树是高度平衡的二叉树,任何节点的两个子树的高度差别<=1 实现AVL树 定义一个AVL树,AVLTree,定义AVLTree的节点内部类AVLNode,节点包含以下特性: 1.key——关 ...

  5. Spring学习笔记:spring整合web之spring-web架包的引用(WebApplicationContextUtils注入容器)

    WebApplicationContextUtils 一.Spring整合web之前 案例:给部门列表添加新部门 import org.apache.log4j.Logger; import org. ...

  6. apache-kylin 权威指南—读书笔记

    1. 概述 kylin 是 OLAP 引擎,采用多维立方体预计算技术,可将大数据的 SQL 查询速度提升到亚秒级别. 需求: 虽然像 spark,hive 等使用 MPP 大规模并行处理和列式存储的方 ...

  7. jenkins学习笔记

    Jenkins 是一款流行的开源持续集成(Continuous Integration)工具,广泛用于项目开发,具有自动化构建.测试和部署等功能.本系列博客以 windows 10 环境为例 1 安装 ...

  8. edge浏览器无法解析<img>的原因

    使用<img>标签插入图片,使用谷歌,ie,等浏览器测试,都可以正常显示图片,但是edge浏览器就是实现不了.经过排查测试,不是文件格式的问题,而是路径带有中文.相对路径中虽然不带中文,但 ...

  9. BZOJ3529: [Sdoi2014]数表(莫比乌斯反演 树状数组)

    题意 题目链接 Sol 首先不考虑\(a\)的限制 我们要求的是 \[\sum_{i = 1}^n \sum_{j = 1}^m \sigma(gcd(i, j))\] 用常规的套路可以化到这个形式 ...

  10. oracle删除归档日志

    查看归档模式: SQL> archive log list; Database log mode Archive Mode Automatic archival Enabled Archive ...