刷题记录(NC14661 简单的数据结构,NC51001 滑动窗口,NC24840 look up,NC50965 Largest Rectangle in Histogram)

NC14661 简单的数据结构

题目链接

关键点: 

1、因为要实现前后段插入和删除元素,因此用deque

2、有调换头尾的操作,因此我们可以记录一个变量来表示当前是否有调换,这样在进行每一步操作时都得判断一下,排序也得判断是从大到小还是从小到大

完整代码

# include <bits/stdc++.h>
using namespace std;
deque<int>q;
int n, m, t = 1;
bool cmp1(int v1, int v2)
{
    return v1<v2;
}
bool cmp2(int v1, int v2)
{
    return v1>v2;
}
int main()
{
    cin>>n>>m;
    for (int i=1; i<=m; i++)
    {
        int x;
        cin>>x;
        if (x==1)
        {
            int data;
            cin>>data;
            if (t==1)
                q.push_front(data);
            else
                q.push_back(data);
        }
        if (x==2)
        {
            if (t==1)
                q.pop_front();
            else
                q.pop_back();
            
        }
        if (x==3)
        {
            int data;
            cin>>data;
            if (t==1)
                q.push_back(data);
            else
                q.push_front(data);
        }
        if (x==4)
        {
            if (t==1)
                q.pop_back();
            else
                q.pop_front();
        }
        if (x==5)
        {
            t = -t;
        }
        if (x==6)
        {
            cout<<q.size()<<endl;
            deque<int>::iterator it;
            int a[500010];
            int pos = 1;
            for (it = q.begin(); it!=q.end(); it++)
            {
                a[pos++] = *it;
            }
            if (t==1)
            {
                for (int i=1; i<pos; i++)
                {
                    if (i<pos-1)
                        cout<<a[i]<<" ";
                    else
                        cout<<a[i];
                }
            }
            else
            {
                for (int i=pos-1; i>=1; i--)
                {
                    if (i>1)
                        cout<<a[i]<<" ";
                    else
                        cout<<a[i];
                }
            }
            cout<<endl;
        }
        if (x==7)
        {
            if (t==1)
            sort(q.begin(), q.end(), cmp1);
            else
                sort(q.begin(), q.end(), cmp2);
        }
    }
    
    
    return 0;
}

NC51001 滑动窗口

题目链接

关键点:

1、找k区间内的最小值为例,用一个双端队列deque,先是判断当前维护的区间是否超出k区间大小,如果超出就排除队头元素。然后每次进队时判断一下队尾的元素大小,如果小于队尾元素,又因为该元素位置为该队头元素的后方,所以只要有该元素存在,该队头元素就不可能为k区间内的最小数,就可以直接pop队尾

2、这样循环判断直到找到比队尾小的元素停止,这时如果维护大小包含一个区间,最小值即为队头元素,然后再将该数据存入队尾

3、我们队列存的是数组下标,方便判断该队列的头是否还在区间内

4、为什么队头每次都是该区间最小的数,每次放入队尾的元素都是保证比队头元素大的,该开始时队头即为队尾,且只有比队尾大的数才放入队尾,比队尾小的元素都直接替代队尾元素了,这时继续判断的队尾都会比队头元素大

完整代码

# include <bits/stdc++.h>
using namespace std;
int n, k;
deque<int>d, q;
int a[10000000+10];
int main()
{
    cin>>n>>k;
    for (int i=1; i<=n; i++)
        cin>>a[i];
    for (int i=1; i<=n; i++)
    {
        if (i - q.front()>=k && !q.empty()) q.pop_front();
        while (!q.empty() && a[i]<=a[q.back()])
            q.pop_back();
        q.push_back(i);
        if (i>=k) cout<<a[q.front()]<<" ";
    }
    cout<<endl;
    for (int i=1; i<=n; i++)
    {
        if (i-d.front()>=k && !d.empty()) d.pop_front();
        while (!d.empty() && a[i]>=a[d.back()]) 
            d.pop_back();
        d.push_back(i);
        if (i>=k) cout<<a[d.front()]<<" ";
    }
    
    
    
    
    return 0;
}

NC24840 look up

题目链接

关键点: 

1、题目要求找每一个点左边第一个大于该点高度的点,因此我们找用栈来维护

2、从最后一个点开始,判断当前元素高度如果大于栈顶元素,就pop,直到找到该栈顶元素会小于该元素为止,这时如果栈有值,那么该top即为该点的仰望对象,如果栈为空,说明该点无仰望对象

3、从最后一个点开始:后面点的仰望对象很明显会影响前面点的 

完整代码

# include <bits/stdc++.h>
using namespace std;
int n;
int a[1000000+10];
stack<int>s;
int l[1000000+10];
int main()
{
    cin>>n;
    for (int i=1; i<=n; i++)
        cin>>a[i];
    s.push(n);
    for (int i=n-1; i>=1; i--)
    {
        while (!s.empty() && a[i]>=a[s.top()]) s.pop();
        if (!s.empty()) l[i] = s.top();
        s.push(i);
    }
    for (int i=1; i<=n; i++)
        cout<<l[i]<<endl;
    
    return 0;
}

NC50965 Largest Rectangle in Histogram

题目链接

关键点: 

1、该题就是找每一个矩形可以伸长的最大距离,然后乘以该矩形的高度,求这个值的最大值

2、同样的找该矩形往左边和往右边能伸长的最大距离,即是找左边第一个小于该矩形高度的下标和右边第一个小于该矩形高度的下标

完整代码

# include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1000000+10;
int n;
int a[1000000+10];
int main()
{
    while (1)
    {
        scanf("%d", &n);
        if (!n)
            break;
        stack<int>l, r;
        int le[N], ri[N];
        for (int i=1; i<=n; i++)
        {
            scanf("%d", &a[i]);
        }
        le[1] = 1;
        l.push(1);
        for (int i=2; i<=n; i++)
        {
            while (!l.empty() && a[i]<=a[l.top()]) l.pop();
            if (!l.empty()) le[i] = l.top()+1;
            else
                le[i]=1;
            l.push(i);
        }
        ri[n] = n;
        r.push(n);
        for (int i=n-1; i>=1; i--)
        {
            while (!r.empty() && a[i]<=a[r.top()]) r.pop();
            if (!r.empty()) ri[i] = r.top()-1;
            else
                ri[i] = n;
            r.push(i);
        }
        ll maxx = 0;
        for (int i=1; i<=n; i++)
        {
            ll x = a[i]*(ri[i]-le[i]+1);
//             cout<<ri[i]<<" "<<le[i]<<endl;
            maxx = max(maxx, x);
        }
        cout<<maxx<<endl;
    }
    
    
    
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值