pb_ds
转自Mistilteinn[https://blog.csdn.net/Mistilteinn/article/details/60325660?locationNum=5&fps=1]
之前玩了玩bp_ds库,发现它的确有好用之处,却也有一些缺陷。
这里只介绍了一些常用用法,详情请见:https://gcc.gnu.org/onlinedocs/libstdc%2B%2B/ext/pb_ds/
1、hash
pbds自带两种hash,分别用的拉链法和查探法,后者要快一些(和我手打的差不多),而且空间更少(见后文例题),所以推荐后者。
头文件:
include<ext/pb_ds/assoc_container.hpp>
include<ext/pb_ds/hash_policy.hpp>
用法:
cc_hash_table是拉链法
gp_hash_table是查探法
除了当数组用外,还支持find和operator[]
例如:__gnu_pbds::gp_hash_table<int,bool> h;
例题:
codevs 1230 元素查找
http://codevs.cn/problem/1230/
我分别测试了一下两种hash
上面的是gp_hash_table。
#include<cstdio>
#include<ext/pb_ds/assoc_container.hpp>//外部的/pb_ds/联系_容器.外部结构的头文件
#include<ext/pb_ds/hash_policy.hpp>//
__gnu_pbds::gp_hash_table<int,bool> h;
inline int read(){
int r=0;char c=getchar();
while(c<'0'||c>'9') {c=getchar();}
while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}
return r;
}
int main(){
int n=read(),m=read(),k;
while(n--){
k=read();
h[k]=true;
}
while(m--){
k=read();
puts(h[k]?"YES":"NO");
}
return 0;
}
2、堆
pbds自带的堆种类很多,但根据我的测试,如果没有合并,stl的优先队列还是更快(包括binary_heap_tag,实际应用中并没有所说的那么快)。所以,也就能用用可并堆了。
头文件:
include<ext/pb_ds/priority_queue.hpp>
用法:
主要用pairing_heap_tag,配对堆,比thin_heap_tag快
和::priority queue用法大致相同,但多了可并堆的join(), modify() , erase() 等
例如: __gnu_pbds::priority_queue<node,less
less是stl里的比较器,需要using namespace std, 也可以换成 greater。
例题:
bzoj 3040: 最短路(road)
http://www.lydsy.com/JudgeOnline/problem.php?id=3040
#include<iostream>
#include<algorithm>
#include<climits>
#include<cstdio>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
const int M=1000005;
inline int read()
{
int r=0;char c=getchar();
while(c<'0'||c>'9') c=getchar();
while(c>='0'&&c<='9') {r=r*10+c-'0';c=getchar();}
return r;
}
struct node
{
int i;
ll v;
node(int a=0,ll c=0){i=a;v=c;}
bool operator < (node b) const
{
return v>b.v;
}
};
typedef __gnu_pbds::priority_queue<node,less<node>,pairing_heap_tag> heap;//!!!
heap::point_iterator hit[M];
heap pq;
int n;
ll d[M];
int last[1000005],cnt;
struct data{int to,next,v;}e[10000005];
void insert(int u,int v,int w)
{
e[++cnt].to=v;e[cnt].next=last[u];last[u]=cnt;e[cnt].v=w;
}
inline void setpath()
{
int T,rxa,rxc,rya,ryc,rp,x,y,z,m;
x=y=z=0;
n=read();m=read();
T=read();rxa=read();rxc=read();rya=read();ryc=read();rp=read();
int a,b,q=min(n,T);
for(int i=0;i<q;i++)
{
x=((ll)x*rxa+rxc)%rp;
y=((ll)y*rya+ryc)%rp;
a=min(x%n+1,y%n+1);
b=y%n+1;
insert(a,b,100000000-100*a);
}
for(int i=0;i<m-T;i++)
{
x=read(),y=read(),z=read();
insert(x,y,z);
}
}
ll dijkstra()
{
for(int i=1;i<=n;i++) d[i]=LLONG_MAX;
hit[1]=pq.push(node(1,0));
d[1]=0;
int o;
while(!pq.empty())
{
o=pq.top().i;
pq.pop();
if(o==n) return d[o];
for(int i=last[o];i;i=e[i].next)
{
if(d[e[i].to]>d[o]+e[i].v)
{
d[e[i].to]=d[o]+e[i].v;
if(hit[e[i].to]==0) hit[e[i].to]=pq.push(node(e[i].to,d[e[i].to]));
else pq.modify(hit[e[i].to],node(e[i].to,d[e[i].to]));
}
}
}
}
int main()
{
setpath();
cout<<dijkstra();
return 0;
}
3、平衡树
pbds最大的好处在于支持名次树和自定义函数
头文件:
include<ext/pb_ds/assoc_container.hpp>
include<ext/pb_ds/tree_policy.hpp>
用法:
常用rb_tree_tag(红黑数)和splay_tree_tag
可以加tree_order_statistics_node_update以实现名次数
注意他没有multiset一样的功能,如果要存重复元素可以建结构体(见例题)。
相比set多了find_by_order和order_of_key(详见例题)
例如:tree<node,null_type,greater
注意老版本编译器要把null_type换成null_mapped_type。
例题:
2004年NOI全国竞赛 郁闷的出纳员
http://codevs.cn/problem/1286/
#include<cstdio>
#include<iostream>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
using namespace std;
struct node{
int v,id;
node(int a,int b){v=a;id=b;}
bool operator >(node b) const
{return v==b.v?id>b.id:v>b.v;}
};
tree<node,null_mapped_type,greater<node>,rb_tree_tag,tree_order_statistics_node_update> T,TE;
int main(){
int n,m,k,s=0,q,ans=0;
char c[10];
scanf("%d%d",&n,&m);
while(n--){
cin>>c[0];scanf("%d",&k);
if(*c=='I') {k+=s;if(k>=m) T.insert(node(k,n));}
else if(*c=='A') m-=k,s-=k;
else if(*c=='S'){
m+=k,s+=k;
T.split(node(m,-1),TE);
ans+=TE.size();
}
else if(*c=='F')
printf(k>T.size()?"-1\n":"%d\n",T.find_by_order(k-1)->v-s);
}
printf("%d\n",ans);
return 0;
}
4、字典树
这个基本没用,就不讲了。。。

浙公网安备 33010602011771号