P2776 题解

· · 题解

积压在做题计划一个多月的题目 (因为我太菜了

看了题解发现大佬们有用队列做的,蒟蒻表示非常膜拜。

不过,对于需要在数组中间插入元素,首先应该想到的是用链表来做啦!

思路

给大家提供一个用链表的思路。

这里我使用了 list。(STL 大法好)

我们以左边为链表的头,右边为链表的尾。

对于 push 操作,我们需要反向遍历一遍整个 list 链表。

为什么需要反向遍历呢?这样可以在找到同一个组的数时插入待插入数并立刻退出遍历,节省时间。

对于 pop 操作,直接弹出最左边(链表的头部)然后清除就好了。

这么简单?对!就是这么简单!

还有不懂的可以看一下代码~

如果你想尝试正向遍历,可以看看这个。

注意事项

在进行反向遍历时,如果使用了迭代器遍历(也只能用这个,除非你不用 list),在声明迭代器指针时请声明成这样:

list<int>::reverse_iterator it

不然会!报!错!

如果不像上面这样声明的话。

代码

接下来是代码时间~

//省略部分头文件
#include<list>  //这个头文件要记得打!
using namespace std;
const int N=5e5+10;

int n,m,cnt,cnt2,k;   
int a[N];
list<int> form;

int main()
{   
    cin>>n>>m;
    for(int i=0;i<n;++i) cin>>a[i];
    cin>>k;
    while(k--)
    {
        string s; int num;

        cin>>s;
        if(s=="push")
        {
            cin>>num;bool flag=0;
            if(form.empty())
            {
                form.push_back(num);
                continue;
            }
            for(list<int>::reverse_iterator it = form.rbegin(); it != form.rend();++it) //反向遍历
            {
                if(a[*it]==a[num]) 
                {
                    flag=1;
                    form.insert( it.base() , num );
                    break;
                }
            }
            if(!flag) form.push_back(num); 
        }
        else 
        {
            cout<<form.front()<<"\n";
            if(!form.empty()) form.pop_front();
        }
    }
    return 0;
}