山东大学程序设计思维实践- TT与可怜的猫

自从 TT 成为了助教,他就热衷于给同学们解答疑问,于是他就没有时间进行陪他的猫猫玩了,真是一只可怜的小猫。

TT 在同一时间会与很多同学同时用 QQ(TT 特供版) 进行答疑,有时 TT 开启一个新的窗口,开始一个新的答疑对话;有时 TT 关闭一个窗口,结束一段答疑; 有时,为了及时回答着急的同学,TT 会把一个对话窗口设置为置顶状态(置顶状态是一种虚拟的状态,窗口的实际位置并不会发生改变)。

你可以将 TT 的聊天窗口想象成一个队列。如果现在没有窗口处于置顶状态,那么在队列中位列第一窗口视为在顶层,否则处于置顶状态的窗口视为在顶层。请注意,不可能同时存在两个窗口处于置顶状态(也就是说,处于置顶状态的窗口,要么不存在,要么只有一个)。如果当前置顶的窗口被关闭了,则剩余队列中第一窗口视为在顶层

TT 为了安抚自己的猫,于是给猫猫看自己的聊天记录解闷,根据猫猫看屏幕中窗口的时间,TT 给每个窗口分配了一个喜爱度,TT 认为喜爱度越高,猫猫越开心。由于猫猫具有不确定的生物特性,所以所有的喜爱度都是不同的。

作为 TT 特供版 QQ 的研发人员,你要负责完成的工作是为软件记录 TT 的操作,形成一个日志系统。日志有固定的记录格式:OpId #X: MSG. ,其中 X 是操作的编号,而 MSG 是日志的提示信息,需要使用特定的字符串进行替换。

TT 可能会用到的操作如下:

  1. Add u: TT 打开一个喜爱度为 u 的新窗口,若 u 不与当前窗口队列中的某个窗口重复,则该新窗口将新建成功,并成为窗口队列中的最后一个窗口。 如果创建成功,则 MSG 记录 success。 否则, MSG 记录 same likeness

  2. Close u: TT 关掉了一个喜爱度为 u 的窗口,如果该窗口存在,则将其关闭,MSG 记录 close u with c,u 表示喜爱度,c 表示该窗口上次打开至今交流的话的数量。若该窗口不存在,则 MSG 记录 invalid likeness

  3. Chat w: TT 和顶层窗口交流了 w 句话,如果当前队列中没有窗口,则 MSG 记录 empty,否则记录 success

  4. Rotate x: 将队列中第 x 个窗口放在队首,若 x 大于当前队列中窗口数或小于 1 ,则 MSG 记录 out of range,否则记录 success。举个例子,目前队列中有喜爱度为 5,3,2,8 的四个窗口,Rotate 3 之后,会将喜爱度为 2 的第 3 个窗口放在首位,结果为 2,5,3,8。

  5. Prior: TT 将目前喜爱度最大的窗口放在队首,如果当前队列中没有窗口,则 MSG 记录 empty,否则记录 success

  6. Choose u: TT 将喜爱度为 u 的窗口放在队首,如果喜爱度为 u 的窗口存在,则 MSG 记录 success,否则记录 invalid likeness

  7. Top u: TT 将喜爱度为 u 的窗口设定为置顶状态,如果喜爱度为 u 的窗口存在,则 MSG 记录 success,否则记录 invalid likeness。注意,处于置顶状态的窗口最多不超过一个,也就是说,如果在此次设定前已经有处于置顶状态的窗口,则原有置顶状态的窗口的置顶状态将会消失。(置顶只是一种虚拟的状态,原窗口在队列中的位置不会发生变化)

  8. Untop: TT 取消当前处于置顶状态窗口的置顶状态。如果当前没有窗口处于置顶状态,则 MSG 记录 no such person,否则记录 success

最后,由于 TT 要给自己的猫猫树立一个讲文明有礼貌的榜样,所以在上述操作完成后,还要进行若干次操作,这些操作是:与当前队列中所有说过话的窗口说拜拜。MSG 记录 Bye u: c, u 表示喜爱度,c 表示该窗口上次打开至今交流的话的数量。即:TT 先和位于顶层的窗口说拜拜,然后将其关闭,如果 TT 没有和当前顶层窗口说过话,则直接将其关闭,如此操作下去,直到队列为空。

输入描述

第一行包含一个整数 T(T≤5),表示数据组数。

对于每组数据,第一行一个 n,表示执行的操作数,其中 0<n≤5000。接下来 n 行,每行输入一个操作,保证所有输入数据中的整数不大于 109。

输出描述

对于每个指定的操作,按照日志的格式,每个操作行。对于最后的非指定操作,同样按照日志的格式,每个操作一行。

测试样例

输入:

1
30
Add 4
Add 3
Chat 4
Add 3
Rotate 2
Chat 5
Prior
Top 3
Choose 4
Rotate 1
Add 2
Close 4
Chat 7
Choose 2
Chat 7
Add 3
Top 2
Add 4
Choose 3
Chat 7
Prior
Top 3
Rotate 1
Rotate 3
Chat 7
Top 4
Add 2
Close 2
Prior
Add 4

输出:

OpId #1: success.
OpId #2: success.
OpId #3: success.
OpId #4: same likeness.
OpId #5: success.
OpId #6: success.
OpId #7: success.
OpId #8: success.
OpId #9: success.
OpId #10: success.
OpId #11: success.
OpId #12: close 4 with 4.
OpId #13: success.
OpId #14: success.
OpId #15: success.
OpId #16: same likeness.
OpId #17: success.
OpId #18: success.
OpId #19: success.
OpId #20: success.
OpId #21: success.
OpId #22: success.
OpId #23: success.
OpId #24: success.
OpId #25: success.
OpId #26: success.
OpId #27: same likeness.
OpId #28: close 2 with 7.
OpId #29: success.
OpId #30: same likeness.
OpId #31: Bye 3: 26.
#include<bits/stdc++>
using namespace std;
typedef long long ll;
#define par pair<ll,ll>
ll n, num;
deque<par> q;

par topt = { 0,0 };

void init()
{
    num = 1;
    topt = { 0,0, };
    while(!q.empty()) q.pop_back();
}

void renew()
{
    if (topt.first == 0)//没有置顶
    {
        return;
    }
    else
    {
        for (ll i = 1; i <= q.size(); ++i)
        {
            if (topt.first == q.front().first)//找到了
            {
                q.front().second = topt.second;
            }

            if (!q.empty())
            {
                q.push_back(q.front());
                q.pop_front();
            }
        }
    }
}

void  add(ll u)//1.打开一个喜爱度为u的新窗口
{
    bool flag = true;
    for (ll i = 1; i <= q.size(); ++i)
    {
        if (q.front().first == u)
        {
            flag = false;
        }
        if (!q.empty())
        {
            q.push_back(q.front());
            q.pop_front();
        }
    }
    if (flag)//没有喜爱度为u的窗口,可以插入队列
    {
        q.push_back({ u, 0 });
        cout << "OpId #" << num << ": success." << endl;
    }
    else cout << "OpId #" << num << ": same likeness." << endl;
}

void close(ll u)//2.关掉一个喜爱度为u的窗口
{
    bool flag = true;
    ll c;//交流的话的数量

    for (ll i = 1; i <= q.size(); ++i)//遍历队列
    {
        if (u == q.front().first)//找到了
        {
            c = q.front().second;
            q.pop_front();
            flag = false;
            if (i > q.size()) break;
        }
        if (!q.empty())
        {
            q.push_back(q.front());
            q.pop_front();
        }
    }
    if (!flag)
    {
        if (u == topt.first)//关闭窗口处于置顶
        {
            topt.first = 0; topt.second = 0;
        }
        cout << "OpId #" << num << ": close " << u << " with " << c << "." << endl;
    }
    else cout << "OpId #" << num << ": invalid likeness." << endl;

}

void chat(ll w)//3.和顶层窗口交流w句话
{
    if (topt.first == 0)//没有置顶
    {
        if (!q.empty())
        {
            q.front().second += w;
            cout << "OpId #" << num << ": success." << endl;
        }
        else cout << "OpId #" << num << ": empty." << endl;
    }
    else//存在置顶窗口
    {
        topt.second += w;
        cout << "OpId #" << num << ": success." << endl;
        renew();//更新队列的值
    }
}

void rotate(ll x)//4.将第x个窗口放在队首
{

    if (x > q.size() || x < 1)//超出范围
    {
        cout << "OpId #" << num << ": out of range." << endl;
        return;
    }
    par te;
    for (ll i = 1; i <= q.size(); ++i)//遍历队列
    {
        if (i == x && (!q.empty()))//找到了第x个窗口
        {
            te = q.front();
            q.pop_front();
            if (i > q.size()) break;//如果是队列最后一个元素直接结束
        }
            q.push_back(q.front());
            q.pop_front();
    }
    q.push_front(te);
    cout << "OpId #" << num << ": success." << endl;
}

void prior()//5.将喜爱度最大的窗口放在队首
{
    if (q.empty())
    {
        cout << "OpId #" << num << ": empty." << endl;
        return;
    }
    ll maxf = 0;
    for (ll i = 1; i <= q.size(); ++i)//遍历找到最大喜爱度
    {
        if (q.front().first > maxf)
        {
            maxf = q.front().first;
        }
        q.push_back(q.front());
        q.pop_front();
    }
    par tem = { maxf,0 };
    for (ll i = 1; i <= q.size(); ++i)//将最大喜爱度的窗口提到队首
    {
        if (q.front().first == maxf)
        {
            tem.second = q.front().second;
            q.pop_front();
            if (i > q.size()) break;
        }
        if (!q.empty())
        {
            q.push_back(q.front());
            q.pop_front();
        }
    }
    q.push_front(tem);
    cout << "OpId #" << num << ": success." << endl;
}

void choose(ll u)//6.将喜爱度为u的放在队首
{
    bool flag = true;
    ll c;
    for (ll i = 1; i <= q.size(); ++i)
    {
        if (u == q.front().first)
        {
            c = q.front().second;
            flag = false;//找到喜爱度为u的窗口
            q.pop_front();
            if (i > q.size()) break;
        }
            q.push_back(q.front());
            q.pop_front();
    }
    if (flag)//没有喜爱度为u的窗口
    {
        cout << "OpId #" << num << ": invalid likeness." << endl;
    }
    else {
        q.push_front({ u,c });
        cout << "OpId #" << num << ": success." << endl;
    }

}

void top(ll u)//7.将喜爱度u的置顶
{
    bool flag = true;
    ll c;
    for (ll i = 1; i <= q.size(); ++i)//找到喜爱度为u的窗口
    {
        if (u == q.front().first)
        {
            c = q.front().second;
            flag = false;
        }
        q.push_back(q.front());
        q.pop_front();
    }

    if (flag)//没有找到
    {
        cout << "OpId #" << num << ": invalid likeness." << endl;
    }
    else//置顶
    {
        topt.first = u;
        topt.second = c;
        cout << "OpId #" << num << ": success." << endl;
    }
}

void untop()//8.取消置顶
{
    if (topt.first == 0)
    {
        cout << "OpId #" << num << ": no such person." << endl;
        return;
    }
    topt = { 0,0 };
    cout << "OpId #" << num << ": success." << endl;
}
void endt()
{
    bool flag = false;//初始无置顶
    ll tem = 0;//标记置顶窗口的喜爱度
    if (topt.first != 0)
    {
        tem = topt.first;
        if (topt.second != 0)
        {
            cout << "OpId #" << num << ": Bye " << topt.first << ": " << topt.second << "." << endl;
            num++;//
        }
        topt.first = 0;
        flag = true;//有置顶窗口
    }
    for (; !q.empty();)
    {
        if (flag && tem == q.front().first)//检测删除置顶窗口
        {
            q.pop_front();
            flag = false;
        }
        if(!q.empty()){
            if (q.front().second != 0)
            {
                cout << "OpId #" << num << ": Bye " << q.front().first << ": " << q.front().second << "." << endl;
                num++;//
            }

            q.pop_front();
        }
    }
}

int main()
{

    ll T;
    cin >> T;
    for (; T != 0; --T)
    {
        init();
        cin >> n;
        string logs;
        ll u;
        for (ll i = 1; i <= n; ++i)
        {
            cin >> logs;
            if (logs == "Add") { cin >> u; add(u); num++; }
            else if (logs == "Close") { cin >> u; close(u); num++; }
            else if (logs == "Chat") {
                cin >> u; chat(u); num++;
            }
            else if (logs == "Rotate") {
                cin >> u; rotate(u); num++;
            }
            else if (logs == "Prior") {
                prior(); num++;
            }
            else if (logs == "Choose") {
                cin >> u; choose(u); num++;
            }
            else if (logs == "Top") {
                cin >> u; top(u); num++;
            }
            else if (logs == "Untop") {
                untop(); num++;
            }
        }
        endt();
    }
    return 0;
}

这道题是我最气的之一,现在想起来也很想扇自己(emmm)

 被这句影响(荼毒),我起手用队列写,结果反而多了复杂操作,直接用数组更简洁。当时写得我都得骂自己是个大聪明(麻),结果最后得91分,卡在倒数第二个点,死活过不去(甚至每句看写注释),结果直到晚上12点都没de出来,求助室友(大佬),他一行一行的看,接近凌晨一点解决(哭)。debug让整个人蚌住了,加上前一天写,两天啥也没干真麻了。

最后说一下问题是队列为空时进行pop操作,虽然很简单,但当时真的给我卡住了,就一个微小的地方没考虑,代码多了后看着真的很。。。加上没有数据集,只能自己想着造。大家参考一下就行,实践写还是建议数组更好操作,便于插入删除——简洁明了。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值