ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

cf1288e Messenger Simulator - 树状数组

2020-12-11 12:35:01  阅读:270  来源: 互联网

标签:const Simulator int 多少 cf1288e Messenger 排名 include 发消息


传送门

类似于qq的,有人给你发消息,那么他就会变成第一个。最后让你求每个人的最小排名和最大排名

首先,对于发过消息的人,最小排名是1,没有发过消息的,最小排名就是他的初始位置\(i\)

对于没有发过消息的,那么他的最大排名就是看所有发过消息的人里面,有多少个人编号大于自己,那么自己就往后多少名
对于发过消息的人,有两种情况,第一种情况就是第一次发消息前有多少人编号大于自己,然后自己就往后移多少名,或者说在两次发消息的间隔里,查看有多少人发了消息,每次就是人数 + 1,但注意的是最后一次发消息后排名还是会变的,所以还要注意查看最后一次发消息到发消息结束的区间。

那么问题转换为在线查询一个区间有多少个数字比我大
以及离散查询一个区间出现了多少种数字

树状数组维护一下就行了

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define ll long long
using namespace std;
const int N = 1e6 + 5;
struct BIT{
    int c[N];
    void init(){memset(c, 0, sizeof(c));}
    int lowbit(int x){
        return x & (-x);
    }
    void add(int k, int x){
        for(; k < N; k += lowbit(k)) c[k] += x;
    }
    int ask(int x){
        ll ans = 0;
        for(; x; x -= lowbit(x)) ans += c[x];
        return ans;
    }
} b;
struct Query{
    int l, r, id;
    bool operator < (const Query &b) const {
        return r < b.r;
    }
} q[N];
int a[N], l[N], r[N], vis[N], last[N], tot;
int main(){
    int n, m; scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++) l[i] = r[i] = i;
    for(int i = 1; i <= m; i++) {
        scanf("%d", &a[i]);
        l[a[i]] = 1;
        int now = b.ask(a[i]) - b.ask(a[i] - 1);
        if(now == 0) {
            b.add(a[i], 1);
        }
        if(!vis[a[i]]) {
            r[a[i]] = max(r[a[i]], a[i] + b.ask(n) - b.ask(a[i]));
            vis[a[i]] = 1;
            last[a[i]] = i;
        } else {
            q[++tot].l = last[a[i]] + 1;
            q[tot].r = i - 1;
            q[tot].id = a[i];
            last[a[i]] = i;
        }
    }
    for(int i = 1; i <= n; i++) {
        if(vis[i]) continue;
        r[i] = max(r[i], b.ask(n) - b.ask(i) + i);
    }
    for(int i = 1; i <= n; i++) {
        if(!vis[i]) continue;
        q[++tot].l = last[i] + 1;
        q[tot].r = m;
        q[tot].id = i;
    }

    sort(q + 1, q + tot + 1);
    memset(vis, 0, sizeof(vis)); b.init();
    int next = 1;
    for(int i = 1; i <= tot; i++) {
        for(int j = next; j <= q[i].r; j++) {
            if(vis[a[j]]) b.add(vis[a[j]], -1);
            b.add(j, 1);
            vis[a[j]] = j;
        }
        next = q[i].r + 1;
        r[q[i].id] = max(r[q[i].id], b.ask(q[i].r) - b.ask(q[i].l - 1) + 1);
    }
    for(int i = 1; i <= n; i++)
        printf("%d %d\n", l[i], r[i]);
    return 0;
}

标签:const,Simulator,int,多少,cf1288e,Messenger,排名,include,发消息
来源: https://www.cnblogs.com/Emcikem/p/14119752.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有