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;
    }
    
  • 相关阅读:
    Max Sum Plus Plus_DP
    Prime Ring Problem_DFS
    Swaps in Permutation _并查集 + 优先队列
    Roadblocks_次短路
    Reward_toposort
    确定比赛名次_toposort
    Zipper_DFS
    Chopsticks_DP
    搬寝室_DP
    Passing the Message_单调栈
  • 原文地址:https://www.cnblogs.com/Emcikem/p/14119752.html
Copyright © 2011-2022 走看看