zoukankan      html  css  js  c++  java
  • p3168 [CQOI2015]任务查询系统(差分+主席树)

    恕我才学浅薄,一开始想到的是树状数组+线段树,然后看了题解才第一次见到了差分这种神奇的科技
    仔细想想,主席树的本质不就是前缀和嘛,加上一个差分也是可以的,没想到真是罪过罪过
    对时间维护一个差分
    在Si处+Ki,在Ti+1处-Ki
    用主席树维护插入的数即可
    不是很复杂就是代码写了好长时间而且越debug越像题解

    注意查前k大的时候比较这样写

        if(lch<kth)
            //向右
        else    
            //向左
    

    不能这样

        if(lch<=kth)
            //向右
        else    
            //向左
    

    因为这样在lch与kth相等的情况下,会一直向左走到还没有开的节点上,导致RE
    丢人的和题解极其相似的代码

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    struct PTNode{
        int lson, rson;
        long long sum, sz;
    }x[100100*40];
    struct Task{
        int Posi,Ki,changew;
        bool operator < (const Task &b) const {
            return Posi < b.Posi;
        }
    }b[100100*3];
    int a[100100], n, m, Nodecnt = 0, cnt = 0, root[100100];
    void pushup(int o){
        x[o].sz = x[x[o].lson].sz + x[x[o].rson].sz;
        x[o].sum = x[x[o].lson].sum + x[x[o].rson].sum;
    }
    void insert(int l, int r, int &now, int pos, int c){
        x[++Nodecnt] = x[now];
        now = Nodecnt;
        x[now].sum += a[pos] *c ;
        x[now].sz += c;
        if(l == r)
            return;
        int mid=(l + r) >> 1;
        if(pos <= mid)
            insert(l, mid, x[now].lson, pos, c);
        else
            insert(mid + 1, r, x[now].rson, pos, c);
    }
    int query(int l, int r, int o, int kth){//前k小
        if(l==r)
            return x[o].sum/x[o].sz*kth;
        int mid=(l+r)>>1,lch=x[x[o].lson].sz;
        if(lch<kth)
            return query(mid+1,r,x[o].rson,kth-lch)+x[x[o].lson].sum;
        else
            return query(l,mid,x[o].lson,kth);
    }
    int main(){
        scanf("%d %d",&m ,&n);
        for(int i = 1; i <= m; i++){
            int x, y, z;
            scanf("%d %d %d",&x, &y, &z);
            b[++cnt] = (Task){x, z, 1};
            b[++cnt] = (Task){y+1, z, -1};
            a[i] = z;
        }
        sort(a + 1, a + m + 1);
        sort(b + 1, b + cnt + 1);
        int j = 1;
        for(int i = 1; i <= n; i++){
            root[i] = root[i-1];
            for(;j <= cnt && b[j].Posi == i;j++){
                int num = lower_bound(a + 1, a + n + 1 , b[j].Ki) - a;
                insert(1, n, root[i], num, b[j].changew);
            }    
        }
        long long preans = 1;
        for(int i = 1;i <= n;i++){
            long long xi,ki,a,b,c;
            scanf("%lld %lld %lld %lld", &xi, &a, &b, &c);
            ki = 1 + (a * preans + b) % c;
            if(ki<=x[root[xi]].sz)
                preans = query(1, n, root[xi], ki);
            else
                preans = x[root[xi]].sum;
            printf("%lld
    ",preans);
        }
        return 0;
    }
    
  • 相关阅读:
    MQTT介绍与使用
    SVN的搭建与使用
    Git版本控制之ubuntu搭建Git服务器
    蓝奏云的速度好快
    放大器的定义和主要参数
    模拟信号导论
    模拟电子电路学习笔记
    二极管单向导电的理解
    让蜂鸣器发声
    蜂鸣器的介绍
  • 原文地址:https://www.cnblogs.com/dreagonm/p/10017096.html
Copyright © 2011-2022 走看看