社区讨论

只用set实现了前五个样例,其后超时,望大佬以此思路优化时间复杂度

学术版参与者 2已保存回复 3

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
3 条
当前快照
1 份
快照标识符
@m3edj9zz
此快照首次捕获于
2024/11/12 19:33
去年
此快照最后确认于
2025/11/04 14:51
4 个月前
查看原帖
注释很详细,大佬请看
CPP
#include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <utility>
#include <set>
using namespace std;
#define N 200010
pair<int, pair<char, int>> F1;//较小的初始位置和对应的性别与实力
pair<int, pair<char, int>> F2;//较大的
vector<pair<int, pair<char, int>>> R(N);//初始数据读入:初始位置,性别,实力
set<pair<int, pair<char, int>>> r;//维护队列,存储当前在队伍中的人:初始位置,性别,实力
pair<int, pair<int, int>> mid;//处理中间值(需要删除的,添加的,都放在这里,存储内容同M
set<pair<int, pair<int, int>>> M;//当前的:相邻异性的实力差,各自的初始位置
vector<pair<int, int>> ans;//存放答案
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        R[i].first = i;//记录进入队伍的初始位置
        cin >> R[i].second.first;//记录性别
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> R[i].second.second;//记录实力
    }
    for (int i = 1; i <= n; i++)
    {
        r.insert(R[i]);//将数据转读至set进行处理(以初始位置升序)
    }
    for (int i = 1; i < n; i++)
    {
        if (R[i].second.first != R[i + 1].second.first)//只要性别不同
        {
            mid.first = abs(R[i].second.second - R[i + 1].second.second);
            mid.second.first = i;
            mid.second.second = i + 1;
            M.insert(mid);
        }
    }
    while (!M.empty())//空了说明没有相邻异性了
    {
        auto p = M.begin();//找到当前实力差最小的
        ans.push_back({(*p).second.first, (*p).second.second});//记录初始位置
        M.erase(*p);//删除这一对
        F1.first = ans.back().first;//记录初始位置靠前的人的位置
        F1.second.first='A';//'A'比G,B都小,loer_bound处理较方便
        auto P1 = lower_bound(r.begin(), r.end(), F1),p1=P1;//获取F1在队列中的指针P1
        if (P1 != r.begin())//防止越界,下面同理
        {
            --p1;//向前判断剔除F1后是否会少一对相邻异性,p1指向前一个人
            if ((*(p1)).second.first != (*P1).second.first)//有的话就删掉原先存进M的数据
            {
                mid.first = abs((*(p1)).second.second - (*P1).second.second);
                mid.second.first = (*(p1)).first;
                mid.second.second = (*P1).first;
                M.erase(mid);
            }
        }
        F2.first = ans.back().second;
        F2.second.first='A';
        auto P2 = lower_bound(r.begin(), r.end(), F2),p2=P2;
        if (P2 != (--r.end()))
        {
            ++p2;//向后剔除
            if ((*(p2)).second.first != (*P2).second.first)
            {
                mid.first = abs((*(p2)).second.second - (*P2).second.second);
                mid.second.first = (*P2).first;
                mid.second.second = (*(p2)).first;
                M.erase(mid);
            }
        }
        if (P2 != (--r.end()) && P1 != r.begin())//是否会产生新的一对相邻异性
        {
            if ((*(p2)).second.first != (*(p1)).second.first)
            {
                mid.first = abs((*(p2)).second.second - (*(p1)).second.second);
                mid.second.first = (*(p1)).first;
                mid.second.second = (*(p2)).first;
                M.insert(mid);
            }
        }
        r.erase(*P1);//把人从队列中剔除
        r.erase(*P2);
    }
    cout << ans.size() << endl;//输出答案组数
    for (auto it : ans)
    {
        cout << it.first << " " << it.second << endl;
    }
}

回复

3 条回复,欢迎继续交流。

正在加载回复...