zoukankan      html  css  js  c++  java
  • 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;
    }
    
  • 相关阅读:
    1062 Talent and Virtue (25 分)
    1083 List Grades (25 分)
    1149 Dangerous Goods Packaging (25 分)
    1121 Damn Single (25 分)
    1120 Friend Numbers (20 分)
    1084 Broken Keyboard (20 分)
    1092 To Buy or Not to Buy (20 分)
    数组与链表
    二叉树
    时间复杂度与空间复杂度
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14119752.html
Copyright © 2011-2022 走看看