zoukankan      html  css  js  c++  java
  • Luogu 3586 [POI2015]LOG

    考虑离散化后开权值线段树。

    设序列中不小于$s$的数有$cnt$个,小于$s$的数的和为$sum$。

    那么操作Z能成功的充要条件是$sum geq (c - cnt) * s$。

    如果序列中不小于$s$的数超过了$c$个,那么直接每一次都选这些数就好了。

    如果没有超过$c$个的话,这$cnt$个数每一次都要选,然后再贪心地取剩下的数中最大的就行了。

    需要把询问中出现的$a, s$和$0$一起离散化。

    细节没想清楚WA好久

    膜Claris

    Code:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e6 + 5;
    const int inf = 1 << 30;
    
    int n, qn, tot = 0, maxn = 0, a[N];
    ll b[N << 1];
    
    struct Querys {
        int type, x, y;
    } q[N];
    
    struct Innum {
        int val, id;
    } in[N << 1];
    
    bool cmp(const Innum &x, const Innum &y) {
        if(x.val != y.val) return x.val < y.val;
        else return x.id < y.id;
    }
    
    inline int max(int x, int y) {
        return x > y ? x : y;
    }
    
    inline void read(int &X) {
        X = 0;
        char ch = 0;
        int op = 1;
        for(; ch > '9' || ch < '0'; ch = getchar())
            if(ch == '-') op = -1;
        for(; ch >= '0' && ch <= '9'; ch = getchar())
            X = (X << 3) + (X << 1) + ch - 48;
        X *= op;
    }
    
    inline void discrete() {
        in[0].val = -inf;
        sort(in + 1, in + 1 + tot, cmp);
        for(int cnt = 0, i = 1; i <= tot; i++) {
            if(in[i].val != in[i - 1].val) cnt++;
            maxn = max(maxn, cnt);
            b[cnt] = in[i].val;
            q[in[i].id].y = cnt;
        }
    }
    
    namespace SegT {
        ll s[N << 3];
        int cnt[N << 3];
        
        #define lc p << 1
        #define rc p << 1 | 1
        #define mid ((l + r) >> 1)
        
        inline void up(int p) {
            if(p) {
                s[p] = s[lc] + s[rc];
                cnt[p] = cnt[lc] + cnt[rc];
            }
        }
        
        void modify(int p, int l, int r, int x, int v) {
            if(x == l && r == x) {
                s[p] += (ll)b[l] * v;
                cnt[p] += v;
                return;
            }
            
            if(x <= mid) modify(lc, l, mid, x, v);
            else modify(rc, mid + 1, r, x, v);
            up(p);
        }
        
        ll qSum(int p, int l, int r, int x, int y) {
            if(x > y) return 0LL;
            if(x <= l && y >= r) return s[p];
            
            ll res = 0LL;
            if(x <= mid) res += qSum(lc, l, mid, x, y);
            if(y > mid) res += qSum(rc, mid + 1, r, x, y);
            return res;    
        }
        
        int qCnt(int p, int l, int r, int x, int y) {
    //        if(x > y) return 0;
            if(x <= l && y >= r) return cnt[p];
            
            int res = 0;
            if(x <= mid) res += qCnt(lc, l, mid, x, y);
            if(y > mid) res += qCnt(rc, mid + 1, r, x, y);
            return res;
        } 
        
    } using namespace SegT;
    
    int main() {
        read(n), read(qn);
        in[++tot] = (Innum) {0, 0};
        for(int i = 1; i <= qn; i++) {
            char op[3]; scanf("%s", op);
            read(q[i].x), read(q[i].y);
            if(op[0] == 'U') q[i].type = 1, in[++tot] = (Innum) {q[i].y, i};
            else q[i].type = 2, in[++tot] = (Innum) {q[i].y, i};
        }
        
        discrete();
        
    /*    for(int i = 1; i <= maxn; i++)
            printf("%lld ", b[i]);
        printf("
    ");
        for(int i = 1; i <= qn; i++)
            printf("%d %d %d
    ", q[i].type, q[i].x, q[i].y);
        printf("
    ");   */
        
        for(int i = 1; i <= n; i++) 
            a[i] = 1, modify(1, 1, maxn, 1, 1);
        
        for(int i = 1; i <= qn; i++) {
            if(q[i].type == 1) {
                modify(1, 1, maxn, a[q[i].x], -1);
                modify(1, 1, maxn, q[i].y, 1);
                a[q[i].x] = q[i].y;    
            } else {
                int cnt = qCnt(1, 1, maxn, q[i].y, maxn);
    /*            if(cnt >= q[i].x) {
                    puts("TAK");
                    continue;
                }   */
                ll sum = qSum(1, 1, maxn, 1, q[i].y - 1);
                if(sum >= (q[i].x - cnt) * b[q[i].y]) puts("TAK");
                else puts("NIE");
            }
        }    
        
        return 0;
    }
    View Code
  • 相关阅读:
    深入探究JVM之垃圾回收器
    深入探究JVM之对象创建及分配策略
    深入探究JVM之内存结构及字符串常量池
    【深度思考】如何优雅告知用户,网站正在升级维护?
    Redis系列(九):Redis的事务机制
    [C#.NET 拾遗补漏]07:迭代器和列举器
    [C#.NET 拾遗补漏]06:单例模式最佳实践
    深入理解 EF Core:使用查询过滤器实现数据软删除
    简化RESTful开发,Spring Data REST让你少掉发
    如何查看Docker容器环境变量,如何向容器传递环境变量
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9524063.html
Copyright © 2011-2022 走看看