Gym - 101572G Galactic Collegiate Programming Contest 树状数组|优先队列

Description

现 在 有 n 个 队 伍 , 每 个 队 伍 的 有 两 个 值 ( a , b ) : 分 别 表 示 通 过 的 题 目 和 罚 时 。 现在有n个队伍,每个队伍的有两个值(a,b):分别表示通过的题目和罚时。 n(a,b):
题 目 越 多 , 排 名 越 靠 前 , 如 果 题 目 数 相 同 则 b 罚 时 越 少 的 队 伍 越 靠 前 。 题目越多,排名越靠前,如果题目数相同则b罚时越少的队伍越靠前。 b
现 在 初 始 化 每 个 人 的 值 都 为 ( 0 , 0 ) 。 现在初始化每个人的值都为(0,0)。 (0,0)
现 在 有 m 次 提 交 , 每 次 操 作 被 定 义 为 ( t , p ) 表 示 第 t 支 队 伍 做 出 了 一 道 题 , 且 罚 时 为 p 现在有m次提交,每次操作被定义为(t,p)表示第t支队伍做出了一道题,且罚时为p m(t,p)tp
要 求 求 出 每 一 提 交 后 第 1 支 队 伍 的 排 名 。 要求求出每一提交后第1支队伍的排名。 1


Input

1 ≤ n , m ≤ 1 0 5 1\leq n,m\leq 10^{5} 1n,m105
1 ≤ t ≤ n 1\leq t \leq n 1tn
1 ≤ p ≤ 1000 1 \leq p \leq 1000 1p1000


Output

输 出 m 行 , 每 行 表 示 提 交 后 队 伍 1 的 排 名 。 输出m行,每行表示提交后队伍1的排名。 m1


Solution

S o l u t i o n 1 \color {red}{Solution 1} Solution1 优先队列模拟
优先级定义为常识。
优 先 队 列 里 存 放 的 都 是 大 于 1 号 队 伍 的 队 伍 优先队列里存放的都是大于1号队伍的队伍 1
考虑用两个数组纪录下每次提交后所有队伍的状态。
修 改 的 队 伍 为 t , 罚 时 为 p 。 修改的队伍为t,罚时为p。 t,p
如 果 修 改 的 不 是 1 号 队 伍 ( t ≠ 1 ) , 更 新 对 应 数 组 。 如果修改的不是1号队伍(t \neq 1),更新对应数组。 1(t̸=1)
更 新 后 如 果 大 于 1 号 队 伍 且 不 在 优 先 队 列 中 , 则 t 是 因 为 这 次 提 交 超 过 了 1 号 , 于 是 加 入 队 列 。 更新后如果大于1号队伍且不在优先队列中,则t是因为这次提交超过了1号,于是加入队列。 1t1
如 果 是 1 号 队 伍 。 更 新 1 号 队 伍 的 信 息 , 然 后 不 断 从 优 先 队 列 弹 出 最 小 的 队 伍 , 如 果 小 于 1 号 就 弹 出 。 如果是1号队伍。更新1号队伍的信息,然后不断从优先队列弹出最小的队伍,如果小于1号就弹出。 111
需 要 注 意 的 是 弹 出 的 队 伍 信 息 可 能 是 之 前 的 , 弹 出 后 需 要 更 新 后 重 新 判 断 是 否 大 于 1 号 并 加 入 队 列 。 需要注意的是弹出的队伍信息可能是之前的,弹出后需要更新后重新判断是否大于1号并加入队列。 1

S o l u t i o n 2 \color {red}{Solution 2} Solution2 离散化+数状数组
离散化
预先处理出每次提交后所有的状态。
排序后获得每个状态的离散后的对应位置。
然后依次更新查询即可。


Codes

c o d e 1 \color {red}{code 1} code1 优先队列模拟

#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+10;
struct Node {
    int id,pro,pen;
    Node(){}
    Node(int _id,int _p,int _e) {id = id;pro = _p;pen = _e;}
    bool operator < (const Node& a) const{
        return (pro < a.pro || (pro == a.pro && pen > a.pen));
    }
    bool operator > (const Node& a) const{
        return (pro > a.pro || (pro == a.pro && pen < a.pen));
    }
};
Node arr[maxn];
bool vis[maxn];
int n,m,t,p;
priority_queue<Node,vector<Node>,greater<Node> > qu;
void cal() {
    while(!qu.empty()) {
        Node tmp = qu.top();
        if(arr[1] < tmp) break;
        qu.pop();
        tmp = arr[tmp.id];
        if(arr[1] < tmp) qu.push(tmp);
        else vis[tmp.id] = false;
    }
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        while(!qu.empty()) qu.pop();
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++) arr[i].id = i,arr[i].pro = arr[i].pen = 0;
        for(int i=0;i<m;i++) {
            scanf("%d%d",&t,&p);
            if(t == 1){
                arr[1].pro++;
                arr[1].pen+=p;
                cal();
            }
            else {
                arr[t].pro++;
                arr[t].pen+=p;
                if(arr[1] < arr[t] && !vis[t]) {
                    vis[t] = true;
                    qu.push(arr[t]);
                }
            }
            printf("%d\n",(int)qu.size()+1);
        }
    }
    return 0;
}

c o d e 2 \color {red}{code 2} code2 离散化树状数组

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 1e5+10;
struct Node {
    int pro,pen;
    Node(){}
    Node(int _p,int _pe){pro = _p;pen = _pe;}
    bool operator == (const Node &a) const {
        return pro == a.pro && pen == a.pen;
    }
    bool operator < (const Node &a) const {
        return (pro < a.pro || (pro == a.pro && pen > a.pen));
    }
    bool operator > (const Node &a) const {
        return (pro > a.pro || (pro == a.pro && pen < a.pen));
    }
};
struct BIT {
    int c[maxn];
    int lowbit(int x) {return x & -x;}
    void init() {
        memset(c,0,sizeof(c));
    }
    void update(int pos,int val) {
        for(int i=pos;i<maxn;i+=lowbit(i)) c[i] += val;
    }
    int sum(int pos) {
        int ans = 0;
        for(int i=pos;i;i-=lowbit(i)) ans += c[i];
        return ans;
    }
}bit;
vector<Node> way;
Node pre,tmp,one;
int n,m,arr[maxn],brr[maxn],qu[maxn],fa[maxn];
int getid(const Node &a) {
    return lower_bound(way.begin(),way.end(),a) - way.begin() + 1;
}
int main()
{
    while(~scanf("%d%d",&n,&m)) {
        memset(arr,0,sizeof(arr));
        memset(brr,0,sizeof(brr));
        way.push_back(Node(0,0));
        for(int i=1,u,v;i<=m;i++) {
            scanf("%d%d",&qu[i],&fa[i]);
            arr[qu[i]]++;brr[qu[i]]+=fa[i];
            way.push_back(Node(arr[qu[i]],brr[qu[i]]));
        }
        sort(way.begin(),way.end());
        
        memset(arr,0,sizeof(arr));
        memset(brr,0,sizeof(brr));
        bit.init();
        bit.update(1,n);
        for(int i=1,pos,now,it;i<=m;i++) {
            pre = Node(arr[qu[i]],brr[qu[i]]);
            arr[qu[i]]++;brr[qu[i]]+=fa[i];
            tmp = Node(arr[qu[i]],brr[qu[i]]);
            one = Node(arr[1],brr[1]);
            pos = getid(pre),now = getid(tmp),it = getid(one);
            bit.update(pos,-1);
            bit.update(now,1);
            int res = n - bit.sum(it);
            printf("%d\n",res+1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值