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;
}
原文地址:https://www.cnblogs.com/dreagonm/p/10017096.html