CSP历年复赛题-P7912 [CSP-J 2021] 小熊的果篮

原题链接:https://www.luogu.com.cn/problem/P7912

题意解读:连在一起的相同水果形成“块”,每一轮从每一块中挑第一个放入篮子,输出每轮挑的水果的编号。

解题思路:

本题要解决几个问题:

1、将水果分块

2、从块中取出第一个水果

3、将剩下的块进行合并,再重复从每一块取出第一个水果

要尽可能减少数据规模,就得在分块上下功夫,对于一个分块的每一个水果,不用存储所有的水果编号,只需要一个结构体,存储起始编号、结束编号,以及标识哪一种水果

struct node //块
{
    int l, r; //该块水果的起始、结束编号
    int value; //该块水果的种类,1:苹果 0:桔子
};

然后,将分块构建之后用queue保存和处理,每一轮取出每一块,已经取出的水果用一个数组flag[]来标记,然后将node.l增加到一个没有删除的编号

如果分块一个水果都没有,则要将该分块从queue中移除

如此取完一轮水果之后,再对所有分块进行合并,为了便于处理,可以定一个两个queue(q1,q2),第一轮从q1分块取水果之后可以将所有分块push进q2,再对q2处理分块合并,然后结果又存入q1。

100分代码:

#include <bits/stdc++.h>
using namespace std;

const int N = 200005;

int n;
int a[N];
struct node //块
{
    int l, r; //该块水果的起始、结束编号
    int value; //该块水果的种类,1:苹果 0:桔子
};
bool flag[N]; //flag[i]=1表示i编号的水果已经被删除
queue<node> q1, q2;

int main()
{
    cin >> n;
    int x;
    for(int i = 1; i <= n; i++) cin >> a[i];
    for(int i = 1; i <= n; i++)
    {
        node nd;
        nd.value = a[i];
        nd.l = nd.r = i;
        int j;
        for(j = i + 1; a[j] == a[j-1] && j <= n; j++)
        {
            nd.r = j;
        }
        q1.push(nd);
        i = j - 1;
    }
    int cnt = n;
    while(q1.size())
    {
        while(q1.size())
        {
            cout << q1.front().l << " "; //输出块中第一个水果编号
            flag[q1.front().l] = 1; //标记删除
            cnt--;
            while(flag[q1.front().l]) //将块的开始编号增加到第一个没有被删除的编号
            {
                q1.front().l++;
            }
            
            if(q1.front().l > q1.front().r) q1.pop();//如果该块编号为空,则移除整个块
            else
            {
                q2.push(q1.front()); //把该块加入q2,待下次使用,队首出队
                q1.pop();
            }
        }
        
        cout << endl;

        //对q2进行块合并,合并后的块放回q1
        while(q2.size())
        {
            node x = q2.front(); //取第一个块
            q2.pop();
    
            while(q2.size()) //找若干与第一个块相同的块,进行合并
            {
                node y = q2.front();
                if(y.value == x.value) //与前一个块相同则合并
                {
                    x.r = y.r; 
                    q2.pop();
                }
                else //与前一个块不同,则跳出开始合并下一系列块
                {
                    break;
                }
            }
            q1.push(x);
        }
    }
    
}

 

posted @ 2024-06-19 09:57  五月江城  阅读(133)  评论(0编辑  收藏  举报