zoukankan      html  css  js  c++  java
  • 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还挺快的……

  • 相关阅读:
    PAT 1006 Sign In and Sign Out
    PAT 1004. Counting Leaves
    JavaEE开发环境安装
    NoSql数据库探讨
    maven的配置
    VMWARE 下使用 32位 Ubuntu Linux ,不能给它分配超过3.5G 内存?
    XCODE 4.3 WITH NO GCC?
    在苹果虚拟机上跑 ROR —— Ruby on Rails On Vmware OSX 10.7.3
    推荐一首让人疯狂的好歌《Pumped Up Kicks》。好吧,顺便测下博客园可以写点无关技术的帖子吗?
    RUBY元编程学习之”编写你的第一种领域专属语言“
  • 原文地址:https://www.cnblogs.com/CzxingcHen/p/9466449.html
Copyright © 2011-2022 走看看