数据结构复习整理
栈
习惯数组实现
int sta[N],top;//栈,栈顶 //压栈 top++; sta[top]=x; //出栈 top--; //清空栈 top=0; //访问栈顶 int a=sta[top]; //判断栈是否非空 bool Empty(){ return top?1:0; }
单调栈
维护一个元素单调递增单调递减的栈,以排除一些不可能的答案。
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std; #define ll long long const int N=1e5+5; ll sta[N],ans,w[N],a[N]; int top; int main(){ int n; scanf("%d",&n); while(n!=0){ for(int i=1;i<=n;i++) scanf("%lld",&a[i]); ans=0;a[n+1]=0;top=0;//处理完栈内所有矩形 for(int i=1;i<=n+1;i++){ if(a[i]>sta[top]){ top++;sta[top]=a[i];w[top]=1; } else{ ll wsum=0; while(sta[top]>a[i]){ wsum+=w[top]; ans=max(ans,wsum*sta[top]); top--; } top++; sta[top]=a[i]; w[top]=wsum+1; } } printf("%lld\n",ans); scanf("%d",&n); } return 0; }
#include<cstdio> #include<iostream> #include<algorithm> #include<cmath> using namespace std; int n; const int N=1e5+5; int sta[N],ans[N],a[N]; int top; int main(){ scanf("%d",&n); for(int i=1;i<=n;i++) scanf("%d",&a[i]); sta[++top]=1; for(int i=2;i<=n;i++){ while(a[i]>a[sta[top]]&&top>0){ ans[sta[top]]=i; top--; } sta[++top]=i; } for(int i=1;i<=n;i++) printf("%d\n",ans[i]); return 0; }
队列:
用STL实现
普通队列:
queue<int>q; q.front();//取队尾元素 q.back();//取队头元素 q.push(x);//将x压入队尾 q.pop();//弹出队头元素 q.empty();//判断队是否为空 q.size()//队内元素个数
双端队列:
deque<int>q; q.push back(x);//在队尾插入元素 q.pop back();//弹出队尾元素 q.push front(x);//在队首插入元素 q.pop front();//弹出队首元素 q.empty();//判断队是否为空 q.size()//队内元素个数 q.front();//取队尾元素 q.back();//取队头元素
优先队列:
priority_queue<int>q;//大根堆 priority_queue<int,vector<int>,greater<int> >q;//小根堆 q.size();//返回q里元素个数 q.empty();//返回q是否为空,空则返回1,否则返回0 q.push(k);//在q的末尾插入k q.pop();//删掉q的第一个元素 q.top();//返回q的第一个元素
单调队列
用双端队列实现,可用来解决 RMQ 问题。
队尾进新元素,队头把无价值的元素弹出。
#include<cmath> #include<cstdio> #include<deque> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int n,k,t; deque<int> q; int a[1000010]; int main(){ scanf("%d %d",&n,&k); for(int i=1;i<=n;i++) scanf("%d",&a[i]); t=1; for(int i=1;i<=n;i++){ while(!q.empty()&&q.back()>=a[i]) q.pop_back(); q.push_back(a[i]); if(i-t>=k&&a[t]==q.front()){ t++; q.pop_front(); } if(i-t>=k&&a[t]!=q.front()) t++; if(i>=k) cout<<q.front()<<' '; } puts(" "); q.clear(); t=1; for(int i=1;i<=n;i++){ while(!q.empty()&&q.back()<=a[i]) q.pop_back(); q.push_back(a[i]); if(i-t>=k&&a[t]==q.front()){ t++; q.pop_front(); } if(i-t>=k&&a[t]!=q.front()) t++; if(i>=k) cout<<q.front()<<' '; } return 0; }
#include<cstdio> #include<iostream> #include<queue> #include<algorithm> #include<cmath> using namespace std; int n,m,ans=-1; const int N=3e5+5; int a[N],sum[N]; deque<int> q; int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } int l=1; q.push_back(0); for(int r=1;r<=n;r++){ if(!q.empty()&&r-q.front()>m){ q.pop_front(); l++; } ans=max(ans,sum[r]-sum[q.front()]); while(!q.empty()&&sum[q.back()]>sum[r]) q.pop_back(); q.push_back(r); } printf("%d",ans); return 0; }
链表
(先咕着)
并查集
实际上是森林用来维护连通性问题的
主要支持查询和合并集合的操作
有启发式合并和路径压缩两种优化方式。一般我们选用路径压缩,两种一起用可以达到 $O(\alpha(n))$的复杂度
//路径压缩 int find(int x){ if(fa[x]==x) return x; return fa[x]=find(fa[x]); }
查询就是:
bool check(int x,int y){ return find(x)==find(y); }
//启发式合并 //把小集合合并到大集合去 void zhi(int u,int v){ u=find(u); v=find(v). if(g[u]<g[v]){ int t; t=u;u=v;v=t; } fa[v]=u; g[u]+=g[v]; }
$Map$
map<string,int> p; //第一个是键的类型,第二个是值的类型 p['c']=1; //map可以使用it->first来访问键,使用it->second访问值 for(map<char,int>::iterator it=mp.begin();it!=mp.end();it++) { cout<<it->first<<" "<<it->second<<endl; }
平衡树
$String$
#include<cstring> string a="123456789"; //定义+初始化 int len=a.length; cin>>a;cout<<a; cout<<a[1];//下标从0开始 string a="abc"; string b="kkk"; string c=a+b; c=="abc kkk"; string s1= "1234567890"; s1.erase(5);//删去从5下标到结束的所有字符 s1.erase(5, 3); //删去下标5开始的3个字符 find_first_of() //函数用于查找子字符串和字符串共同具有的字符在字符串中首次出现的位置。 find(s1,0) //从第2个参数开始找 rfind(s1,0) //至多找到第二个参数

浙公网安备 33010602011771号