专栏文章
"7-31晚 单调栈和单调队列"总结
个人记录参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miol9u8e
- 此快照首次捕获于
- 2025/12/02 21:03 3 个月前
- 此快照最后确认于
- 2025/12/02 21:03 3 个月前
考试情况
错题总结(不含T8、T9)
T3:
死因:不开unsigned long long 见祖宗
错误片段:
CPP#include<bits/stdc++.h>
#define int long long
#define endl '\n'
const int N=1e6+5;
using namespace std;
正确:
CPP#include<bits/stdc++.h>
#define int unsigned long long
#define endl '\n'
const int N=1e6+5;
using namespace std;
正确代码:
CPP单调队列模版,唯一的就是要开unsigned long long
#include<bits/stdc++.h>
#define int unsigned long long
#define endl '\n'
const int N=1e6+5;
using namespace std;
int n,m,a[1000005],mi[1000005];
deque<int>q;
void solve();
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
solve();
return 0;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<m;i++){
while(q.size()&&a[q.back()]<=a[i])q.pop_back();
q.push_back(i);
}
for(int i=m;i<=n;i++){
while(q.size()&&a[q.back()]<=a[i]){
q.pop_back();
}
if(i>m){
if(q.size()&&q.front()==i-m)q.pop_front();
}
q.push_back(i);
cout<<q.size()<<endl;
}
}
T4:
死因:只正着跑了一遍,但还要清空再倒着跑一遍
错误片段:
CPP for(int i=1;i<=n;i++){
while(st.size()&&a[st.top()]>=a[i])ans+=i-st.top()+1,st.pop();
if(st.size())ans+=st.top()-i+1;
st.push(i);
}
...
...
cout<<ans*2;
正确:
CPP for(int i=n;i>=1;i--){
while(st.size()&&a[i]>=a[st.top()])st.pop();
if(st.size())ans+=st.top()-i+1;
st.push(i);
}
while(st.size())st.pop();
for(int i=1;i<=n;i++){
while(st.size()&&a[i]>a[st.top()])st.pop();
if(st.size())ans+=i-st.top()+1;
st.push(i);
}
cout<<ans;
正确代码:
CPP就是单调栈,但正向跑完一遍还要清空栈并反向跑一遍(先正先反都可以)还要注意:ans加的距离不要搞错了,加错了ans加的有可能是负数。(不能加abs)
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,a[1000005],ans;
stack<int>st;
signed main(){
cin>>n;
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=n;i>=1;i--){
while(st.size()&&a[i]>=a[st.top()])st.pop();
if(st.size())ans+=st.top()-i+1;
st.push(i);
}
while(st.size())st.pop();
for(int i=1;i<=n;i++){
while(st.size()&&a[i]>a[st.top()])st.pop();
if(st.size())ans+=i-st.top()+1;
st.push(i);
}
cout<<ans;
return 0;
}
T5:
死因:理解错误
错误片段:
CPPfor(int i=1;i<=n;i++){
while(st1.size()&&a[st1.top()]>a[i])st1.pop(),ans++;
if(st1.size()&&a[i]!=a[st1.top()])st1.push(i);
if(i==1)st1.push(i);
}
正确:
CPPfor(int i=1;i<=n;i++){
while(st1.size()&&a[st1.top()]>a[i])st1.pop(),ans++;
if(st1.size()&&a[i]==a[st1.top()])continue;
st1.push(i);
}
正确代码
CPP首先,宽度没有任何作用,如果想要海报数最少,至少这堵墙可以用一张海报贴完,不可能一堵墙用两三张海报,所以宽度没用然后维护一个单调递增的栈,如果遇到栈顶小于a[i],就将栈顶出栈,并ans++。如果栈顶和a[i]高度相等,这两个可以合并成一堵墙,宽度为a[i]和st.top()的宽度之和,但宽度没用,所以实际上如果,a[i]是不用进栈的。最后直接输出即可
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
const int N=1e6+5;
using namespace std;
int n,a[N],ans;
stack<int>st1;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
int ffff;
cin>>ffff>>a[i];
}
for(int i=1;i<=n;i++){
while(st1.size()&&a[st1.top()]>a[i])st1.pop(),ans++;
if(st1.size()&&a[i]==a[st1.top()])continue;
st1.push(i);
}
cout<<ans+st1.size();
return 0;
}
T6:
死因:can't do it(不会做)
错误片段:
不要看了,随机数(果然不能相信随机数)
正确代码
CPP首先把所有数据存到一个结构体数组s[]里,并按位置从小到大排序。然后遍历s数组,用一个num数组存每一种珍珠在队列里的数量,cnt存在队列里的颜色数量。每次将进队的珍珠的颜色加1,如果这个珍珠颜色原来没有,cnt++。若颜色数量大于等于种类数,即,就把队首出队,如果出队的这个珍珠的颜色数量变成0了,cnt--。minn代表彩带的最短长度,彩带长度为队尾位置-队首位置。若果minn大于彩带长度,更新minn。最后输出minn。
#include<bits/stdc++.h>
#define int long long
#define endl '\n'
const int N=1e6+5;
using namespace std;
int n,k,tot,num[N],minn=1e18,cnt;
struct node{
int pos,id;
}s[N];
bool cmp(node x,node y){
return x.pos<y.pos;
}
deque<int>q;
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>k;
for(int i=1;i<=k;i++){
int t;
cin>>t;
while(t--){
int x;
cin>>x;
tot++;
s[tot].pos=x;
s[tot].id=i;
}
}
sort(s+1,s+n+1,cmp);
for(int i=1;i<=n;i++){
q.push_back(i);
int id=s[i].id;
if(num[id]==0)cnt++;
num[id]++;
while(q.size()&&cnt>=k){
int j=q.front();
q.pop_front();
int id=s[j].id;
num[id]--;
if(num[id]==0){
cnt--;
minn=min(minn,s[i].pos-s[j].pos);
}
}
}cout<<minn;
return 0;
}
T7:
死因:似乎忘记怎么写了
错误片段:
几乎全错
正确代码:
CPP这题有一个问题:任意两个人之间的人可以等于这两个人的较小值,导致之前的代码无法通过。我们可以定义一个结构体node,用来存储高度和数量。输入数组s和栈都是node类型。遍历数组s,如果s[i].h大于等于栈顶的高度,sum加上栈顶的数量,如果s[i].h等于栈顶的高度s[i]的数量加上栈顶的数量,然后把栈顶出栈。如果栈里面还有元素,sum++。最后将s[i]压入栈。最后输出sum。
#include<bits/stdc++.h>
#define int long long
using namespace std;
int a[10000005];
struct node{
int h,num;
}s[100005];
stack<node>st;
int n;
int sum;
signed main()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>s[i].h;
s[i].num=1;
}
for(int i=1;i<=n;i++)
{
while(st.size()&&s[i].h>=st.top().h)
{
sum+=st.top().num;
if(s[i].h==st.top().h){
s[i].num+=st.top().num;
}
st.pop();
}
if(st.size()){
sum++;
}
st.push(s[i]);
}
cout<<sum;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...