题目描述

小$w$来到天堂的门口,对着天堂的大门发呆。
大门上有一个二分图,左边第$i$个点连到右边第$p_i$个点。(保证$p_i$是一个排列)。
小$w$每次可以找左边某个对应连线尚未被移除的点$i$,付出$c_i$的代价之后删除左边第$i$个点到右边第$p_i$个点的连线,以及所有和它们相交的连线。
请问小$w$最少要花多少钱来删除所有连线?


输入格式

一行一个整数$n$表示两边点的个数。
一行$n$个整数表示$p_i$。
一行$n$个整数表示$c_i$。


输出格式

一行一个整数表示答案。


样例

样例输入:

5
3 1 4 5 2
3 4 3 4 1

样例输出:

5


数据范围与提示

对于$20\%$的数据,$n\leqslant 10$。
对于$40\%$的数据,$n\leqslant 1,000$。
对于另外$20\%$的数据,$|i-p_i|\leqslant 5$。
对于$100\%$的数据,$n\leqslant 2\times {10}^5,c_i\leqslant 10,000$。


题解

认真思考一下问题,其实我们就是要求一个极长上升序列。

设$dp[i]$表示左边最后一个选的谁的最大贡献。

每次转移的时候枚举一个前面既不相交,又能保证极长的$j$转移。

然而这样做的时间复杂度显然是$\Theta(n^2)$的。

因为$j$满足单调性,其一定是一个上升序列,那么我们可以用线段树来维护这个上升序列。

时间复杂度:$\Theta(n\log^2n)$。

期望得分:$100$分。

实际得分:$100$分。


代码时刻

#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int n;
int p[200001],c[200001];
int trmax[1000000],trmin[1000000];
int res,dp[200001];
void askmax(int x,int l,int r,int L,int R)
{
if(r<L||R<l)return;
if(L<=l&&r<=R)
{
res=max(res,trmax[x]);
return;
}
int mid=(l+r)>>1;
askmax(L(x),l,mid,L,R);
askmax(R(x),mid+1,r,L,R);
}
int ask(int x,int l,int r,int w)
{
if(w>trmax[x])return 1<<30;
if(l==r)return dp[trmax[x]];
int mid=(l+r)>>1;
if(w>trmax[R(x)])return ask(L(x),l,mid,w);
return min(trmin[x],ask(R(x),mid+1,r,w));
}
void pushup(int x,int l,int r)
{
trmax[x]=max(trmax[L(x)],trmax[R(x)]);
int mid=(l+r)>>1;
if(trmax[R(x)]==-1044266559)trmin[x]=ask(L(x),l,mid,0);
else trmin[x]=ask(L(x),l,mid,trmax[R(x)]);
}
void change(int x,int l,int r,int d,int w)
{
if(l==r)
{
trmax[x]=w;
return;
}
int mid=(l+r)>>1;
if(d<=mid)change(L(x),l,mid,d,w);
else change(R(x),mid+1,r,d,w);
pushup(x,l,r);
}
int askmin(int x,int l,int r,int R)
{
if(R<l)return 1<<30;
if(r<=R)
{
if(r+1<=R)
{
res=-1;
askmax(1,1,n,r+1,R);
return ask(x,l,r,res);
}
return ask(x,l,r,0);
}
int mid=(l+r)>>1;
return min(askmin(L(x),l,mid,R),askmin(R(x),mid+1,r,R));
}
int main()
{
memset(trmax,-0x3f,sizeof(trmax));
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&p[i]);
for(int i=1;i<=n;i++)
scanf("%d",&c[i]);
change(1,0,n,0,0);
for(int i=1;i<=n;i++)
{
dp[i]=askmin(1,0,n,p[i])+c[i];
change(1,0,n,p[i],i);
}
cout<<askmin(1,0,n,n);
return 0;
}

rp++

[CSP-S模拟测试]:God Knows(线段树维护单调栈)的更多相关文章

  1. [CSP-S模拟测试]:陶陶摘苹果(线段树维护单调栈)

    题目传送门(内部题116) 输入格式 第一行两个整数$n,m$,如题 第二行有$n$个整数表示$h_1-h_n(1\leqslant h_i\leqslant 10^9)$ 接下来有$m$行,每行两个 ...

  2. [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)

    题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...

  3. 洛谷 P4198 楼房重建 线段树维护单调栈

    P4198 楼房重建 题目链接 https://www.luogu.org/problemnew/show/P4198 题目描述 小A的楼房外有一大片施工工地,工地上有N栋待建的楼房.每天,这片工地上 ...

  4. [BZOJ 2957]楼房重建(THU2013集训)(线段树维护单调栈)

    题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2957 分析: 根据题意,就是比较斜率大小 只看一段区间的话,那么这段区间能看见的楼房数量就是这 ...

  5. 【洛谷5294】[HNOI2019] 序列(主席树维护单调栈+二分)

    点此看题面 大致题意: 给你一个长度为\(n\)的序列\(A\),每次询问修改一个元素(只对当前询问有效),然后让你找到一个不下降序列\(B\),使得这两个序列相应位置之差的平方和最小,并输出这个最小 ...

  6. [CSP-S模拟测试]:Weed(线段树)

    题目描述 $duyege$的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹.为了查出真相,$duyege$准备修好电脑之后再进行一次金坷垃的模拟实验.电脑上面有若干层金坷垃,每次只能在上面撒上一层高度 ...

  7. [CSP-S模拟测试]:string(线段树)

    题目描述 给定一个由小写字母组成的字符串$s$. 有$m$次操作,每次操作给定$3$个参数$l,r,x$. 如果$x=1$,将$s[l]~s[r]$升序排序: 如果$x=0$,将$s[l]~s[r]$ ...

  8. Contest Hunter 模拟赛09 A [线段树维护斜率]

    题面 传送门 思路 首先看看我们到底要干什么:有$1e6$次询问,遍历$i$,每次要求一个形如$b_i \ast a_j - a_i \ast b_j$的东西的最大值 考虑如果一个$j$的决策在当前的 ...

  9. Wannafly挑战赛18 E 极差(线段树、单调栈)

    Wannafly挑战赛18 E 极差 题意 给出三个长度为n的正整数序列,一个区间[L,R]的价值定义为:三个序列中,这个区间的极差(最大值与最小值之差)的乘积. 求所有区间的价值之和.答案对\(2^ ...

随机推荐

  1. C++ 编写的DLL导出的函数名乱码含义解析

    C++编译时函数名修饰约定规则: __stdcall调用约定:   1.以"?"标识函数名的开始,后跟函数名:     2.函数名后面以"@@YG"标识参数表的 ...

  2. Python 操作 mongodb 亿级数据量使用 Bloomfilter 高效率判断唯一性 例子

    工作需要使用 python 处理 mongodb 数据库两亿数据量去重复,需要在大数据量下快速判断数据是否存在 参考资料:https://segmentfault.com/q/101000000061 ...

  3. 手撸红黑树-Red-Black Tree 入门

    一.学习红黑树前的准备: 熟悉基础数据结构 了解二叉树概念 二.红黑树的规则和规则分析: 根节点是黑色的 所有叶子节点(Null)是黑色的,一般会认定节点下空节点全部为黑色 如果节点为红色,那么子节点 ...

  4. Island Transport 【HDU - 4280】【最大流Dinic】

    题目链接 可以说是真的把时间卡爆了,不断的修改了好多次之后才A了,一直T一直T,哭了…… 可以说是很练时间优化了,不断的改,不断的提交,最后竟然是改了Dinic中的BFS()中,我们一旦搜索到了T之后 ...

  5. Java中的基本类型和包装类型区别

    首先看一下几个测试题,验证一下java中对基本类型和包装类型的理解,看看最后输出的答案对不对,答案在这篇博客中哦: // 第一题: 基本类型和包装类型 int a = 100; Integer b = ...

  6. vuejs基础-跑马灯效果

    <!DOCTYPE html><html lang="en"> <head> <meta charset="UTF-8" ...

  7. python支持的进程与线程

    一.multiprocessing模块介绍 python中的多线程无法利用CPU资源,在python中大部分情况使用多进程.python中提供了非常好的多进程包multiprocessing. mul ...

  8. ELK日志分析系统之logstash7.x最新版安装与配置

    2 .Logstash的简介 2.1 logstash 介绍 LogStash由JRuby语言编写,基于消息(message-based)的简单架构,并运行在Java虚拟机(JVM)上.不同于分离的代 ...

  9. python------模块和包及异常处理

    一.模块 所有的模块导入都应该尽量往上写,且顺序为: a:内置模块 b:扩展模块 c:自定义模块 #my_module.py print('from the my_module.py') money= ...

  10. css样式表的引入方式

    一般来说,css 有两种样式表的引入方式,在这里我记录一下,比较这两种引入方式的区别: <link rel="stylesheet" type="text/css& ...