更新日志:
update on 10.12
完善了队列内容
更新了二分
(未完待续。。。)
更新队列:vector,deque,set,bitset,nth_element以及一些神奇函数
本文同步更新于我的luogu blog
前言:
STL是个好东西,可以帮助我们较快懒的构建程序。
虽然这玩意儿常数大
但在时间复杂度正确的情况下,一般不会有人xian de dan teng去卡STL的。
在本蒟蒻会的前提下整理的,可能不全
目录:
队列&优先队列
二分(lower_bound&upper_bound)
正文
这玩意儿应该挺好理解,大佬们把它优化的很好了,一般排序就用它就ok
输入:
10
5465 12 54 6 21 54 315 1 0 1
#include<cstdio> #include<algorithm>//sort所在头文件 using namespace std;//sort const int N=10005; int n,a[N]; int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1); /* a:排序数组名称 1:起始下标 n:数组长度 */ for(int i=1;i<=n;i++) { printf("%d ",a[i]); } return 0; }
输出
0 1 1 6 12 21 54 54 315 5465
sort排序一般默认为从小到大排,若想要从大到小排,我们可以重定义其中的比较函数,代码如下:
#include<bits/stdc++.h> using namespace std; const int N=10005; int n,a[N]; bool cmp(int a,int b) { return a>b; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d",&a[i]); } sort(a+1,a+n+1,cmp); /* cmp:比较函数 */ for(int i=1;i<=n;i++) { printf("%d ",a[i]); } return 0; }
输出:
5465 315 54 54 21 12 6 1 1 0
当然,我们也可以根据实际需要对cmp函数做出相应更改:
如,对结构体排序:
#include<cstdio> #include<algorithm>//sort所在头文件 using namespace std;//sort const int N=10005; int n; struct qwq{ int x,y; }; qwq a[N],b[N]; bool cmp(const qwq &a,const qwq &b) { return a.x==b.x?a.y<b.y:a.x>b.x; //以结构体中x为第一关键字降序排列,y升序排列 /*等价于 if(a.x==b.x)return a.y<b.y; else return a.x>b.y; */ } bool com(const qwq &a,const qwq &b) { return a.y==b.y?a.x<b.x:a.y<b.y; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++) { scanf("%d%d",&a[i].x,&a[i].y); b[i].x=a[i].x,b[i].y=a[i].y; } sort(a+1,a+n+1,cmp); sort(b+1,b+n+1,com); /* com,cmp:比较函数 */ printf(" "); for(int i=1;i<=n;i++) { printf("%d %d ",a[i].x,a[i].y); } printf(" "); for(int i=1;i<=n;i++) { printf("%d %d ",b[i].x,b[i].y); } return 0; } /*输入: 10 3 5 9 8 4 6 1 0 3 8 6 1 2 2 8 5 1 9 7 2 a数组输出: 9 8 8 5 7 2 6 1 4 6 3 5 3 8 2 2 1 0 1 9 b数组输出: 1 0 6 1 2 2 7 2 3 5 8 5 4 6 3 8 9 8 1 9 */
队列&优先队列
#include<queue>
啊,这可真是个好东西苍蝇搓手ing
queue
queue 模板类的定义在queue头文件中。
queue 模板类需要两个模板参数,一个是元素类型,一个容器类型,元素类型是必要的,容器类型是可选的,默认为deque 类型。
queue兹磁的常见操作:
#include<iostream> #include<queue> using namespace std; int n,x; queue <int>q; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>x; q.push(x);//入队,将x接到队列的末端 int tail=q.back();//访问队尾元素,即最后被压入队列的元素 cout<<tail<<" "; } cout<<endl; while(!q.empty())//判断队列空,当队列空时,返回true { cout<<"size"<<q.size()<<" ";//访问队列中的元素个数 int TOP=q.front();//访问队首元素 cout<<TOP<<endl; q.pop();//出队,弹出队列的第一个元素,并不会返回被弹出元素的值 } return 0; }
等价于以下手写代码
#include<iostream> using namespace std; int n,x; int q[10005],head=1,tail=0; int main() { cin>>n; for(int i=1;i<=n;i++) { cin>>x; q[++tail]=x; cout<<q[tail]<<" "; } cout<<endl; while(head<=tail) { cout<<"size:"<<tail-head+1<<" "; cout<<q[head]<<endl; head++; } return 0; }
一组数据: 输入: 10 1 2 3 4 5 6 7 8 9 0 输出: queue: 1 2 3 4 5 6 7 8 9 0 size10 1 size9 2 size8 3 size7 4 size6 5 size5 6 size4 7 size3 8 size2 9 size1 0 手写队: 1 2 3 4 5 6 7 8 9 0 size10 1 size9 2 size8 3 size7 4 size6 5 size5 6 size4 7 size3 8 size2 9 size1 0
priority_queue
优先队列和队列有神马不同呢?
优先队列不同于队列,队列是先进先出,优先队列是大数先出(默认)
#include<iostream> #include<queue> using namespace std; int n,x; priority_queue<int>q; int main() { /* 输入: 10 1 3 5 2 0 4 9 7 8 10 */ cin>>n; for(int i=1;i<=n;i++) { cin>>x; q.push(x); cout<<q.top()<<" "; } /* 输入时队头输出: 1 3 5 5 5 5 9 9 9 10 */ cout<<endl; while(!q.empty()) { cout<<q.top()<<" "; q.pop(); } /* 出队顺序: 10 9 8 7 5 4 3 2 1 0 */ return 0; }
如果宁仔细看看就会发现这个B优先队列它其实是个大根堆(默认)
那我想用优先队列实现dij堆优该咋办呢?
手写堆
重载比较函数
要小根堆的话,可以
1.重载operator
2.c++友情提供的greater<>
懒得放代码了
友情赠送一份堆优dij代码
1 #include<bits/stdc++.h> 2 #include<queue> 3 #define ll long long 4 #define fo(a,b,c) for(register int a=b;a<=c;a++) 5 #define fr(a,b,c) for(register int a=b;a>=c;a--) 6 7 using namespace std; 8 const int N=100005; 9 const int M=500005; 10 const int inf=INT_MAX; 11 int n,m,s; 12 int vi,ui,wi; 13 int dis[N]; 14 bool v[N]; 15 inline int read() 16 { 17 int x=0,f=1; 18 char ch=' '; 19 while(ch<'0'||ch>'9') 20 { 21 if(ch=='-')f=-1; 22 ch=getchar(); 23 } 24 while(ch>='0'&&ch<='9') 25 { 26 x=(x<<3)+(x<<1)+ch-'0'; 27 ch=getchar(); 28 } 29 return x*f; 30 } 31 inline void write(int x) 32 { 33 int y=10,len=1; 34 while(y<=x) 35 { 36 y*=10; 37 len++; 38 } 39 while(len--) 40 { 41 y/=10; 42 putchar(x/y+'0'); 43 x%=y; 44 } 45 } 46 int to[M],h[M],w[M],nx[M],cnt=0; 47 inline void add(int u,int v,int k) 48 { 49 to[++cnt]=v; 50 nx[cnt]=h[u]; 51 h[u]=cnt; 52 w[cnt]=k; 53 } 54 struct node{ 55 int dis,u; 56 bool operator <(const node& rsh)const{ 57 return rsh.dis<dis; 58 } 59 }; 60 priority_queue<node> q; 61 inline void dij() 62 { 63 fo(i,1,n)dis[i]=inf; 64 dis[s]=0; 65 q.push((node){0,s}); 66 while(!q.empty()) 67 { 68 node tmp=q.top(); 69 q.pop(); 70 int x=tmp.u,d=tmp.dis; 71 if(v[x])continue; 72 v[x]=1; 73 for(int i=h[x];i;i=nx[i]) 74 { 75 int y=to[i]; 76 if(dis[y]>dis[x]+w[i]) 77 { 78 dis[y]=dis[x]+w[i]; 79 if(!v[y]) 80 { 81 q.push((node){dis[y],y}); 82 } 83 } 84 } 85 } 86 } 87 int main() 88 { 89 memset(v,0,sizeof(v)); 90 n=read(),m=read(),s=read(); 91 fo(i,1,m) 92 { 93 ui=read(),vi=read(),wi=read(); 94 add(ui,vi,wi); 95 //add(vi,ui,wi); 96 } 97 dij(); 98 fo(i,1,n) 99 { 100 printf("%d ",dis[i]); 101 //write(dis[i]);putchar(' '); 102 } 103 return 0; 104 }
二分
lower_bound()和upper_bound()
先说说限制条件:
由于是二分做法,我们需要保证单调性,即必须在有序数组
内实现
关于这俩函数的作用: 如果我们有一个有序序列a(大小为n)和一个x
lower_bound():找出一个有序数组
中第一个大于等于x的值;
upper_bound():找出一个有序数组
中第一个大于x的值;
dui,这俩货就差个‘=’有序数组!,我已经强调了四次了!
用法:
lower_bound(a+1,a+1+n,x); upper_bound(a+1,a+n+1,x);
与大多数stl相同,它们也可以重载比较方式
桥豆麻袋!比较方式??那么问题来了!什么有序序列??
好了我又要开始强调了qwq
有序:
对于比较器有序,且必须是升序
比较器默认是"<";
Q:如果要在一个下降序列里寻找一个小于x的数呢?
cmp cmp cmp!!!
bool cmp(int a,int b) { return a>b; }
qwq...
有没得c++友情提供的greater<>??懒癌晚期实锤
有!:
lower_bound(a+1,a+1+n,x,greater<int>()); upper_bound(a+1,a+1+n,x,greater<int>());
奥对,这个东东返回的是一个指针
以lower_bound()为例
输出a中的第一个大于等于x的值处理
int p=lower_bound(@#^#$^%)-a; cout<<a[p]<<endl; /////////////// int *p=lower_bound( $#&@%$ !); cout<<*p<<endl;
lower_bound和upper_bound可以优化LIS
给出一些例题qwq
未完待续....