• cf1288e Messenger Simulator


    传送门

    类似于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
    ", l[i], r[i]);
        return 0;
    }
    
  • 相关阅读:
    Python面试题目之Python函数默认参数陷阱
    Python面试题目之列表取值超出范围
    Python面试题目之打乱打乱有序列表
    Python面试题目之列表去重并维持原来顺序
    Python面试题目之字典排序
    前端学习笔记之JavaScript
    前端学习笔记之CSS后代选择器、子元素选择器、相邻兄弟选择器区别与详解
    前端学习笔记之CSS知识汇总
    SQL学习笔记八之ORM框架SQLAlchemy
    高效循环算法
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14119752.html
Copyright © 2020-2023  润新知