bzoj 3932 [CQOI2015]任务查询系统 (主席树)

题目大意:有n个任务,有起始时间si和结束时间ei,以及该任务重要度pi,求某时刻xi正在进行的任务中,重要度前ki小任务的重要度之和

本以为是一道主席树的水题,可我调了半个多小时才调出来,原来是我新建的主席树根的左右儿子并没继承上个版本,导致某些时刻并没有任何刚开始或刚结束的任务,而在这个时间却找不到这个时刻对应的主席树。

然而我只有80分

看了题解,发现我忽略了一种情况,当很多个任务重要度相同时,可能前ki小个任务并不能把这些任务都取到,特判即可

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
#define N 100100
#define ui unsigned int 
#define il inline
#define ll long long 
#define rint register int
using namespace std;

int n,m,ctt,ma,tot;
int root[N];
ll a[N];
struct Seg{int ls,rs;ll sum,sz;}seg[N*50];
vector<ll>S[N];
vector<ll>E[N];

int gc(){
    int rett=0,fh=1;char p=getchar();
    while(p<'0'||p>'9') {if(p=='-')fh=-1;p=getchar();}
    while(p>='0'&&p<='9') {rett=(rett<<3)+(rett<<1)+p-'0';p=getchar();}
    return rett*fh;
}
void build(int l,int r,int rt)
{
    if(l==r) return;
    int mid=(l+r)>>1;
    seg[rt].ls=++tot,build(l,mid,seg[rt].ls);
    seg[rt].rs=++tot,build(mid+1,r,seg[rt].rs);
}
il void pushup(int rt)
{seg[rt].sum=seg[seg[rt].ls].sum+seg[seg[rt].rs].sum;
 seg[rt].sz=seg[seg[rt].ls].sz+seg[seg[rt].rs].sz;}
void update(int x,int l,int r,int rt1,int rt2,ll val)
{
    if(l==r) {seg[rt2].sz+=val,seg[rt2].sum+=val*a[l];return;}
    int mid=(l+r)>>1;
    if(x<=mid){
        if(!seg[rt2].ls||seg[rt2].ls==seg[rt1].ls){
            seg[rt2].ls=++tot,seg[seg[rt2].ls].sz=seg[seg[rt1].ls].sz;
            seg[seg[rt2].ls].sum=seg[seg[rt1].ls].sum;
            if(!seg[rt2].rs) seg[rt2].rs=seg[rt1].rs;
        }update(x,l,mid,seg[rt1].ls,seg[rt2].ls,val);
    }else{
        if(!seg[rt2].rs||seg[rt2].rs==seg[rt1].rs){
            seg[rt2].rs=++tot,seg[seg[rt2].rs].sz=seg[seg[rt1].rs].sz;
            seg[seg[rt2].rs].sum=seg[seg[rt1].rs].sum;
            if(!seg[rt2].ls) seg[rt2].ls=seg[rt1].ls;
        }update(x,mid+1,r,seg[rt1].rs,seg[rt2].rs,val);
    }pushup(rt2);
}
ll query(ll w,int l,int r,int rt)
{
    if(l==r){
        if(w<seg[rt].sz) return (ll)a[l]*w;
        else return seg[rt].sum;  
    } 
    int mid=(l+r)>>1;
    if(seg[seg[rt].ls].sz>=w) return query(w,l,mid,seg[rt].ls);
    else return seg[seg[rt].ls].sum+query(w-seg[seg[rt].ls].sz,mid+1,r,seg[rt].rs);
}

int main()
{
    scanf("%d%d",&m,&n);
    int x,y,w;ll z;
    for(int i=1;i<=m;i++){
        x=gc(),y=gc(),z=gc();
        a[++ctt]=z,S[x].push_back(z),E[y+1].push_back(z);
    }
    sort(a+1,a+ctt+1);
    ma=unique(a+1,a+ctt+1)-(a+1);
    a[ma+1]=0x3f3f3f3f;
    root[0]=++tot,build(1,ma,root[0]);
    for(int i=1;i<=n;i++){
        root[i]=++tot;
        seg[root[i]].ls=seg[root[i-1]].ls;
        seg[root[i]].rs=seg[root[i-1]].rs;
        seg[root[i]].sz=seg[root[i-1]].sz;
        seg[root[i]].sum=seg[root[i-1]].sum;
        for(int j=0;j<S[i].size();j++){
            int pos=lower_bound(a+1,a+ma+1,S[i][j])-a;
            update(pos,1,ma,root[i-1],root[i],(ll)1);
        }
        for(int j=0;j<E[i].size();j++){
            int pos=lower_bound(a+1,a+ma+1,E[i][j])-a;
            update(pos,1,ma,root[i-1],root[i],(ll)-1);
        }
    }
    ll ans=1;
    ll s1,s2,s3;
    for(int i=1;i<=n;i++){
        x=gc(),s1=gc(),s2=gc(),s3=gc();
        s1=(s1*ans+s2)%s3+1ll;
        ans=query(s1,1,ma,root[x]);
        printf("%lld\n",ans);
    }
    return 0;
}


猜你喜欢

转载自blog.csdn.net/guapisolo/article/details/82468362