[CQOI2015]任务查询系统

link

几乎是一个可持久化线段树板子,但是调了半天,因为有一个坑点。此题要维护一个加点,删点的线段树,查找前$k$小的和,所以可以想到差分维护删除。先将优先级离散化,然后每次通过时间建树,内容存的是优先级,然后就慢慢去写就行,最后发现有一步是if(l==r) return sum[rt]/size[rt]*tot,里面$sum[i]$表示当前以i为节点的优先级之和,$size[i]$表示里面还有几个任务,因为有可能都选会超过所要求的,所以要除以下,并且那个坑点是$size[rt]$有可能为$0$,所以就炸了,就这个坑调了半天

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll long long
using namespace std;
inline int read(){
    int f=1,ans=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){ans=ans*10+c-'0';c=getchar();}
    return f*ans;
}
const int MAXN=100050;
struct node{
    int pos,tag,val,valv;
}x[MAXN<<1];
int cnt,ls[MAXN<<7],rs[MAXN<<7],tr[MAXN<<7],n,m,pos;
ll sum[MAXN<<7];
int size[MAXN<<7],val[MAXN];
bool cmp(node x1,node x2){
    return x1.pos<x2.pos;
}
int st;
void build(int &rt,int l,int r){
    rt=++st;
    if(l==r) return;
    int mid=l+r>>1;
    build(ls[rt],l,mid),build(rs[rt],mid+1,r);
    return;
}
void update(int &rt,int las,int l,int r,int xx,int tag){
    rt=++st;ls[rt]=ls[las],rs[rt]=rs[las],sum[rt]=sum[las],size[rt]=size[las];
    sum[rt]+=tag*(ll)val[xx],size[rt]+=tag;
    if(l==r) return;
    int mid=l+r>>1;
    if(xx<=mid) update(ls[rt],ls[las],l,mid,xx,tag);
    else update(rs[rt],rs[las],mid+1,r,xx,tag);
    return;
}
int query(int rt,int l,int r,int tot){
    if(tot>=size[rt]) return sum[rt];
    if(l==r) return sum[rt]/size[rt]*tot;
    int mid=l+r>>1,siz=size[ls[rt]];ll res=0;
    if(tot<=siz) res+=query(ls[rt],l,mid,tot);
    else res+=sum[ls[rt]]+query(rs[rt],mid+1,r,tot-siz);
    return res;
}
ll pre=1;
signed main(){
    n=read(),m=read();
    for(int i=1;i<=n;i++){
        x[++cnt].pos=read(),x[cnt].tag=1;
        x[++cnt].pos=read()+1,x[cnt].tag=-1,x[cnt].val=x[cnt-1].val=val[i]=read();
    }
    sort(val+1,val+n+1);
    sort(x+1,x+cnt+1,cmp);
    int d=unique(val+1,val+n+1)-(val+1);
    for(int i=1;i<=cnt;i++) x[i].valv=lower_bound(val+1,val+n+1,x[i].val)-val;
    build(tr[0],1,d);
    pos=1;
    for(int i=1;i<=m;i++){
        tr[i]=tr[i-1];
        while(x[pos].pos==i){
            update(tr[i],tr[i],1,d,x[pos].valv,x[pos].tag);pos++;
        }
    }
    for(int i=1;i<=m;i++){
        int time=read(),a=read(),b=read(),c=read();
        int k=1+(a*pre+b)%c;
        if(sum[tr[time]]<=k) printf("%lld
",pre=sum[tr[time]]);
        else printf("%lld
",pre=query(tr[time],1,d,k));
    }
}
View Code
原文地址:https://www.cnblogs.com/si-rui-yang/p/10059321.html