FZU 2029 买票问题 树状数组+STL

题目链接:买票问题

思路:优先队列维护忍耐度最低的人在队首,leave操作ok.
vis数组记录从1到n的编号的人们是不是在队列中,top维护队首的人的编号。pop操作搞定。
然后,check操作就是在vis数组中查找当前编号之前有多少个为1的数,树状数组大法好。
啊...数据虽然很大,但是t<=100000,所以可以用map把所有的编号标记为1-100000之间的...

dbug全程:开始树状数组求和错误,检查模板没错,后猛然想起,树状数组每次更新i处的值,所有小于maxn的i + lowbit(i)都要更新,所以,sum()函数里,while(i<=maxn) 而不是当前最大位置num。然后发现RE,用mp数组映射的时候,mp[int] = num++; 显然mp数组越界了。果断该成map。大概这就是map的好处吧...然后TLE,我拒绝相信!然后发现队列没有清空,直接开在main函数了,AC之。尝试把队列开成全局变量,然后main函数里清空,依然TLE。

大概,STL用的太多了吧..........

附代码:

/*
 不想敲题,不想敲题,这道题真丑~躺在地上打滚中...
 思路:优先队列维护忍耐度最低的人在队首,leave操作ok.
 vis数组记录从1到n的编号的人们是不是在队列中,top维护队首的人的编号。pop操作搞定。
 然后,check操作就是在vis数组中查找当前编号之前有多少个为1的数,树状数组大法好。
 啊...数据虽然很大,但是t<=100000,所以可以用map把所有的编号标记为1-100000之间的...
 讲真,为什么dangshixiangbuchulaine...
*/

#include <stdio.h>
#include <string.h>
#include <iostream>
#define maxn 100005
#include <map>
#include <queue>
using namespace std;

char op[10];
int vis[maxn];
map<int, int>mp;
int a[maxn];
int num;

struct Node {
    int id, endu;
    friend bool operator < (Node a, Node b) {
        return a.endu > b.endu; // 从小到大
    }
    Node(int id, int endu) {
        this->id = id, this->endu = endu;
    }
};

int lowbit(int x) {
    return x & (-x);
}

int sum(int id) {
    int ans = 0;
    while(id > 0) {
        ans += a[id];
        id -= lowbit(id);
    }
    return ans;
}

void update(int id, int x) {
    while(id <= maxn) {
        a[id] += x;
        id += lowbit(id);
    }
}



int main() {
    int n;
    while(~scanf("%d", &n)) {
        mp.clear();
        num = 1; // 编号
        memset(vis, 0, sizeof(vis));
        memset(a, 0, sizeof(a));
        priority_queue<Node> que;
        int top = 0;

        for (int i=0; i<n; ++i) {
            scanf("%s", op);
            if (op[0] == 'a') {
                int id, endu;
                scanf("%d%d", &id, &endu);
                mp[id] = num++;
                id = mp[id];
                vis[id] = 1;
                update(id, 1);
                Node temp(id, endu);
                que.push(temp);
            }
            else if (op[0] == 'l') {
                while(!que.empty() && !vis[que.top().id])
                        que.pop();
                if (!que.empty() && vis[que.top().id]) {
                    int lid = que.top().id;
                    que.pop();
                    vis[lid] = 0;
                    update(lid, -1);
                }
            }
            else if (op[0] == 'p') {
                while(!vis[top] && top<num) top++;
                if (top < num && vis[top]) {
                    vis[top] = 0;
                    update(top, -1);
                }
            }
            else {
                int tid, tendu;
                scanf("%d%d", &tid, &tendu);
                tid = mp[tid];
                if (vis[tid]) {
                    int tsum = sum(tid);
                    tsum -= 1;
                    printf("%d
", tsum);
                    if (tsum > tendu) {
                        vis[tid] = 0;
                        update(tid, -1);
                    }
                }
            }
        }
    }
    return 0;
}

不然,把struct改成pair好了...

附代码:

/*
 不想敲题,不想敲题,这道题真丑~躺在地上打滚中...
 思路:优先队列维护忍耐度最低的人在队首,leave操作ok.
 vis数组记录从1到n的编号的人们是不是在队列中,top维护队首的人的编号。pop操作搞定。
 然后,check操作就是在vis数组中查找当前编号之前有多少个为1的数,树状数组大法好。
 啊...数据虽然很大,但是t<=100000,所以可以用map把所有的编号标记为1-100000之间的...
 讲真,为什么dangshixiangbuchulaine...
*/

#include <stdio.h>
#include <string.h>
#include <iostream>
#define maxn 100005
#include <map>
#include <queue>
using namespace std;

char op[10];
int vis[maxn];
map<int, int>mp;
int a[maxn];
int num;

typedef pair<int, int>Per;


int lowbit(int x) {
    return x & (-x);
}

int sum(int id) {
    int ans = 0;
    while(id > 0) {
        ans += a[id];
        id -= lowbit(id);
    }
    return ans;
}

void update(int id, int x) {
    while(id <= maxn) {
        a[id] += x;
        id += lowbit(id);
    }
}



int main() {
    int n;
    while(~scanf("%d", &n)) {
        mp.clear();
        num = 1; // 编号
        memset(vis, 0, sizeof(vis));
        memset(a, 0, sizeof(a));
        priority_queue<Per, vector<Per>, greater<Per> > que; // 从小到大
        int top = 0;
        Per per;

        for (int i=0; i<n; ++i) {
            scanf("%s", op);
            if (op[0] == 'a') {
                int id, endu;
                scanf("%d%d", &id, &endu);
                mp[id] = num++;
                id = mp[id];
                vis[id] = 1;
                update(id, 1);
                per = make_pair(endu, id);
                que.push(per);
            }
            else if (op[0] == 'l') {
                while(!que.empty() && !vis[que.top().second])
                        que.pop();
                if (!que.empty() && vis[que.top().second]) {
                    int lid = que.top().second;
                    que.pop();
                    vis[lid] = 0;
                    update(lid, -1);
                }
            }
            else if (op[0] == 'p') {
                while(!vis[top] && top<num) top++;
                if (top < num && vis[top]) {
                    vis[top] = 0;
                    update(top, -1);
                }
            }
            else {
                int tid, tendu;
                scanf("%d%d", &tid, &tendu);
                tid = mp[tid];
                if (vis[tid]) {
                    int tsum = sum(tid);
                    tsum -= 1;
                    printf("%d
", tsum);
                    if (tsum > tendu) {
                        vis[tid] = 0;
                        update(tid, -1);
                    }
                }
            }
        }
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/icode-girl/p/5372584.html