Black Box 是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量 i。最开始的时候 Black Box 是空的.而 i=0。这个 Black Box 要处理一串命令。 命令只有两种: - `ADD(x)`:把 x 元素放进 Black Box; - `GET`:i 加 1,然后输出 Black Box 中第 i 小的数。 记住:第 i 小的数,就是 Black Box 里的数的按从小到大的顺序排序后的第 i 个元素。 我们来演示一下一个有11个命令的命令串。(如下表所示) | 序号 | 操作 | i | 数据库 | 输出 | | :--: | :--- | :------: | ------ | :----: | | 1 | `ADD(3)` | 0 | 3 | / | | 2 | `GET` | 1 | 3 | 3 | | 3 |`ADD(1)`|1|1,3|/| | 4 |`GET`|2|1,3|3| | 5 |`ADD(-4)`|2|−4,1,3|/| | 6 |`ADD(2)`|2|−4,1,2,3|/| | 7 |`ADD(8)`|2|−4,1,2,3,8|/| | 8 |`ADD(-1000)`|2|−1000,−4,1,2,3,8|/| | 9 |`GET`|3|−1000,−4,1,2,3,8|1| | 10 |`GET`|4|−1000,−4,1,2,3,8|2| | 11 |`ADD(2)`|4|−1000,−4,1,2,2,3,8|/| 现在要求找出对于给定的命令串的最好的处理方法。`ADD` 命令共有 m 个,`GET` 命令共有 n 个。现在用两个整数数组来表示命令串: 1. a1,a2,⋯,am:一串将要被放进 Black Box 的元素。例如上面的例子中 a=[3,1,−4,2,8,−1000,2]。 2. u1,u2,⋯,un:表示第 ui 个元素被放进了 Black Box 里后就出现一个 `GET` 命令。例如上面的例子中 u=[1,2,6,6] 。输入数据不用判错。
输入格式
第一行两个整数 m 和 n,表示元素的个数和 `GET` 命令的个数。 第二行共 m 个整数,从左至右第 i 个整数为 ai,用空格隔开。 第三行共 n 个整数,从左至右第 i 个整数为 ui,用空格隔开。
输出格式
输出 Black Box 根据命令串所得出的输出串,一个数字一行。
输入样例 #1
输出样例 #1
#### 数据规模与约定 - 对于 30% 的数据,1≤n,m≤104。 - 对于 50% 的数据,1≤n,m≤105。 - 对于 100% 的数据,1≤n,m≤2×105,|ai|≤2×109,保证 u 序列单调不降。
---------------------------
OIER 公司是一家大型专业化软件公司,有着数以万计的员工。作为一名出纳员,我的任务之一便是统计每位员工的工资。这本来是一份不错的工作,但是令人郁闷的是,我们的老板反复无常,经常调整员工的工资。如果他心情好,就可能把每位员工的工资加上一个相同的量。反之,如果心情不好,就可能把他们的工资扣除一个相同的量。我真不知道除了调工资他还做什么其它事情。 工资的频繁调整很让员工反感,尤其是集体扣除工资的时候,一旦某位员工发现自己的工资已经低于了合同规定的工资下界,他就会立刻气愤地离开公司,并且再也不会回来了。每位员工的工资下界都是统一规定的。每当一个人离开公司,我就要从电脑中把他的工资档案删去,同样,每当公司招聘了一位新员工,我就得为他新建一个工资档案。 老板经常到我这边来询问工资情况,他并不问具体某位员工的工资情况,而是问现在工资第 k 多的员工拿多少工资。每当这时,我就不得不对数万个员工进行一次漫长的排序,然后告诉他答案。 好了,现在你已经对我的工作了解不少了。正如你猜的那样,我想请你编一个工资统计程序。怎么样,不是很困难吧? 如果某个员工的初始工资低于最低工资标准,那么将不计入最后的答案内。
输入格式
第一行有两个非负整数 n 和 min。n 表示下面有多少条命令,min 表示工资下界。 接下来的 n 行,每行表示一条命令。命令可以是以下四种之一: - `I k` 新建一个工资档案,初始工资为 k。如果某员工的初始工资低于工资下界,他将立刻离开公司。 - `A k` 把每位员工的工资加上 k 。 - `S k` 把每位员工的工资扣除 k。 - `F k` 查询第 k 多的工资。 在初始时,可以认为公司里一个员工也没有。
输出格式
对于每条 `F` 命令,你的程序要输出一行,仅包含一个整数,为当前工资第 k 多的员工所拿的工资数,如果 k 大于目前员工的数目,则输出 −1。 输出文件的最后一行包含一个整数,为离开公司的员工的总数。
输入样例 #1
输出样例 #1
- `I` 命令的条数不超过 105; - `A` 和 `S` 命令的总条数不超过 100; - `F` 命令的条数不超过 105; - 每次工资调整的调整量不超过 103; - 新员工的工资不超过 105。
介绍
什么是__gnu_pbds?Policy based data structures!简称平板电视pbds。在使用pbds前,你需要:
woc,真jb烦,有没有什么简单的方法?当然有:
但是在dev c++里如果这样写,会提示少一个文件,出各种莫名奇妙的锅,其它的IDE请自行尝试,我的linux是deepin的,装了NOI Linux的dalao帮忙测一下。
hash
该引用的头文件和命名空间都讲过了,直接进入正题。
hash_table的用法与map类似,它是这么定义的:
其中cc开头为拉链法,gp开头为探测法,个人实测探测法稍微快一些。
啥?操作?其实就和map差不多,支持[ ]和find。

等一等?和map一样,那不如直接用map了。不不不,map的总时间复杂度是 O(nlogn) 的,而hash_table的总时间复杂度仅为 O(n) !所以我们可以用这个特性来做洛谷P1333 瑞瑞的木棍。前置知识:并查集 欧拉路。
感谢Great_Influence的代码:
tree
pbds里面的tree都是平衡树,其中有rb_tree,splay_tree,ov_tree(后两种都容易超时,所以请不要用它们)。需要的头文件与命名空间也讲了,下面我们来看它的食用方法:
下面我们来试一试洛谷P3369 普通平衡树(感谢shenben的代码):
在看这里之前,你需要熟练地掌握c++的特性。如果看不懂我也没有办法,你可以跳过这一部分。
你以为pbds种的tree只能实现这些功能?不不不,你可以自定义它,我们需要写一个自己的node_update,它是长这样的:
我们先解释一下这个类是如何工作的。节点更新的tree都会保存一个my_type类型的变量。当我们修改这棵树的时候,会从叶子节点开始修改,并且每次都会调用operator(),我们来看一下这个函数的两个参数:
Node_Itr it为调用该函数的元素的迭代器,Node_CItr end_it可以const到叶子节点的迭代器,Node_Itr有以下的操作:
1.get_l_child(),返回其左孩子的迭代器,没有则返回node_end;
2.get_r_child(),同get_l_child();
3.get_metadata(),返回其在树中维护的数据;
4.**it可以获取it的信息。
为了详细讲解,我们举一个更新子树大小的例子:
现在我们学会了更新,那么我们该如何自己写操作呢?node_update所有public方法都会在树中公开。如果我们在node_update中将它们声明为virtual,则可以访问基类中的所有virtual。所以,我们在类里添加以下内容:
这样我们就能直接访问树了,还有,node_begin指向树根,node_end指向最后一个叶子节点的后一个地址,下面这个就是查排名的操作:
下面我们来看CF459D:
trie
trie即为字典树,我们先看如何定义一个trie与它的操作:
现在我们来看Astronomical Database:
priority_queue
priority_queue为优先队列,用堆实现,priority_queue的定义与操作:
时间复杂度:

堆优化dijkstra(感谢Great_Influence的代码):
#include<bits/stdc++.h>
#include<ext/pb_ds/priority_queue.hpp>
#define Rep(i,a,b) for(register int i=(a),i##end=(b);i<=i##end;++i)
#define Repe(i,a,b) for(register int i=(a),i##end=(b);i>=i##end;--i)
#define For(i,a,b) for(i=(a),i<=(b);++i)
#define Forward(i,a,b) for(i=(a),i>=(b);--i)
#define Chkmax(a,b) a=a>b?a:b
template<typename T>inline void read(T &x)
{
T f=1;x=0;char c;
for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-1;
for(;isdigit(c);c=getchar())x=x*10+(c^48);
x*=f;
}
inline void write(int x)
{
if(!x){putchar(48);putchar('\n');return;}
static int sta[45],tp;
for(tp=0;x;x/=10)sta[++tp]=x%10;
for(;tp;putchar(sta[tp--]^48));
putchar('\n');
}
using namespace std;
void file()
{
#ifndef ONLINE_JUDGE
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
#endif
}
const int MAXN=1e5+7,MAXM=4e5+7;
static int n,m;
static struct edg
{
int u,v,w,h;
friend bool operator<(edg a,edg b){return a.h>b.h;}
}EDG[MAXM];
static struct edge
{
int v,w,nxt;
}P[MAXM<<1];
static int head[MAXN],e;
inline void add(int u,int v,int w)
{P[++e]=(edge){v,w,head[u]};head[u]=e;}
__gnu_pbds::priority_queue<pair<int,int>,greater<pair<int,int> > >G;
__gnu_pbds::priority_queue<pair<int,int>,greater<pair<int,int> > >::point_iterator its[MAXN];
static int dis[MAXN];
const int INF=2e9+7;
inline void dijkst(int s)
{
G.clear();
its[s]=G.push(make_pair(0,s));dis[s]=0;
Rep(i,2,n)dis[i]=INF,its[i]=G.push(make_pair(INF,i));
static int u;
while(!G.empty())
{
u=G.top().second;G.pop();
for(register int v=head[u];v;v=P[v].nxt)
if(dis[P[v].v]>dis[u]+P[v].w)
{
dis[P[v].v]=dis[u]+P[v].w;
G.modify(its[P[v].v],make_pair(dis[u]+P[v].w,P[v].v));
}
}
}
static int s;
inline void init()
{
read(n);read(m);read(s);
static int u,v,w;
Rep(i,1,m)read(u),read(v),read(w),add(u,v,w);
}
inline void solve()
{
dijkst(s);
Rep(i,1,n)printf("%d ",dis[i]);
puts("");
}
int main()
{
file();
init();
solve();
return 0;
}
关于rope
sorry,rope属于__gnu_cxx,不属于__gnu_pbds。下次讲ext中其他的内容时,我会讲rope。
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
2017-04-24 [国家集训队2011]旅游(宋方睿)