• Luogu 3168 [CQOI2015]任务查询系统


    区间修改单点查询,又观察到是一个k小,考虑主席树上做差分
    一开始样例疯狂挂,后来发现主席树在一个历史版本上只能修改一次,所以要开2*n个根结点,记录一下每个时间对应的根结点编号
    然后80分,考虑到当一个排名的结点有w个而查询的k<w时会使答案变大,所以特判(但是一开始又喜闻乐见地把符号写反了)~
    一通乱改+疯狂提交后水过

    Code:

    #include <cstdio>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef long long ll;
    
    const int N = 1e5 + 5;
    const ll inf = (ll)1 << 60;
    
    int n, qn, bel[N], maxn = 0;
    ll val[N];
    vector <int> ins[N], del[N];
    
    struct Task {
        int st, ed;
        ll pri;
    } a[N];
    
    struct Innum {
        int id;
        ll val;
    } in[N];
    
    bool cmp(const Innum &x, const Innum &y) {
        if(x.val != y.val) return x.val < y.val;
        else return x.id < y.id;
    }
    
    template <typename T>
    inline void read(T &X) {
        X = 0;
        char ch = 0;
        T 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 int max(int x, int y) {
        return x > y ? x : y;
    }
    
    inline void discrete() {
        in[0].val = -inf;
        sort(in + 1, in + 1 + n, cmp);
        int cnt = 0;
        for(int i = 1; i <= n; i++) {
            if(in[i].val != in[i - 1].val) ++cnt;
            maxn = max(maxn, cnt);
            val[cnt] = in[i].val;
            a[in[i].id].pri = cnt;
        }
    } 
    
    struct Node {
        int lc, rc, cntSum;
        ll priSum;
    };
    
    namespace PSegT {
        int root[N << 1], nodeCnt;
        Node s[N * 40];
        
        #define mid (l + r) / 2
        
        inline void up(int p) {
            s[p].cntSum = s[s[p].lc].cntSum + s[s[p].rc].cntSum;
            s[p].priSum = s[s[p].lc].priSum + s[s[p].rc].priSum;
        }
            
        void insert(int &p, int l, int r, int x, int pre, int type) {
            p = ++nodeCnt;
            s[p] = s[pre];
            s[p].cntSum += type;
            s[p].priSum += (ll)type * val[x];
    
            if(l == r) return;
            
            if(x <= mid) insert(s[p].lc, l, mid, x, s[pre].lc, type);
            else insert(s[p].rc, mid + 1, r, x, s[pre].rc, type);
            
    //        up(p);
        }
        
        ll query(int p, int l, int r, int k) {
    //        if(l == r) return s[p].priSum;
            if(l == r) return k < s[p].cntSum ? (ll)k * val[l] : s[p].priSum;
            int now = s[s[p].lc].cntSum; ll res = 0;
            if(k <= now) res = query(s[p].lc, l, mid, k);
            else res = s[s[p].lc].priSum + query(s[p].rc, mid + 1, r, k - now);
            return res;
        }
        
        void print(int p, int l, int r) {
            printf("(%d %d %d %d %lld) ", p, s[p].lc, s[p].rc, s[p].cntSum, s[p].priSum);
            if(l == r) return;
            print(s[p].lc, l, mid);
            print(s[p].rc, mid + 1, r);
        }
        
        #undef mid
        
    } using namespace PSegT;
    
    int main() {
        read(n), read(qn);
        for(int i = 1; i <= n; i++) {
            read(a[i].st), read(a[i].ed), read(a[i].pri);
            in[i].val = a[i].pri, in[i].id = i;
            ins[a[i].st].push_back(i);
            del[a[i].ed + 1].push_back(i); 
        }
        discrete();
        
        nodeCnt = root[0] = 0;
        int rtCnt = 0;
        for(int i = 1; i <= qn; i++) {
            for(unsigned int j = 0; j < ins[i].size(); j++) 
                ++rtCnt, insert(root[rtCnt], 1, maxn, a[ins[i][j]].pri, root[rtCnt - 1], 1);
            for(unsigned int j = 0; j < del[i].size(); j++) 
                ++rtCnt, insert(root[rtCnt], 1, maxn, a[del[i][j]].pri, root[rtCnt - 1], -1); 
            bel[i] = rtCnt;
        }
        
    /*    for(int i = 1; i <= rtCnt; i++, printf("
    "))
            print(root[i], 1, maxn);   */
        
        ll ans = 1;
        for(int x, k, _a, _b, _c; qn--; ) {
            read(x), read(_a), read(_b), read(_c);
            k = 1 + ((ll)_a * ans + _b) % _c;
            if(k >= s[root[bel[x]]].cntSum) printf("%lld
    ", ans = s[root[bel[x]]].priSum);
            else printf("%lld
    ", ans = query(root[bel[x]], 1, maxn, k));
        }   
        
        return 0;
    }

    感觉vector还挺快的……

  • 相关阅读:
    Phone List(字典树)
    Dating with girls(1)(二分+map+set)
    Color the ball(树状数组+线段树+二分)
    python模块导入总结
    Python爬虫之定时抢购淘宝商品
    Celery多队列配置
    python垃圾回收机制
    python变量、对象和引用你真的明白了吗
    使用 supervisor 管理 Celery 服务
    Supervisor的作用与配置
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9466449.html
Copyright © 2020-2023  润新知