洛谷P3168 [CQOI2015]任务查询系统

又是一道主席树板子题,喜闻乐见,然而我还是非常智障。

之前写的题都是单点修改区间查询,这道题变成了区间修改单点查询,然后我一度懵逼…之后发现,是不是在蓝书上学树状数组的时候,就见过类似的转化?

哦,成,差分

完美把区间修改变成单点修改,询问的时候只需要询问T[X]…(X是询问的时间点)。根据差分数组的定义,差分数组到某一位置的前缀和就是某一位置应有的统计数。

然后比较智障的是调试的时候修改了update里原来忽略了离散化的影响的部分,但是query里忘了…导致用离散化以后的数值去给答案做贡献,就这样居然还有八十分…

改掉以后就快乐AC啦。需要好好想想的地方不少,需要再仔细过一遍。

#include 
#include
#include
#include
using namespace std;
int n,m,tim=1,all;
int T[2*100010*20],L[2*100010*20],R[2*100010*20],tot,c[100010],d[100010],cnt[2*100010*20];
long long sum[2*100010*20],lst=1;
struct node{
    int t,p,val;
}a[200010];
bool cmp(node x,node y){
    if(x.treturn true;
    else return false;
}
void build(int &p,int l,int r){
    p=++all;
    if(l==r)return;
    int mid=(l+r)/2;
    build(L[p],l,mid);
    build(R[p],mid+1,r);
} 
void update(int &p,int pre,int l,int r,int x,int val){
    p=++all;
    L[p]=L[pre],R[p]=R[pre],cnt[p]=cnt[pre]+val,sum[p]=sum[pre]+d[x]*val;
    if(l==r)return;
    int mid=(l+r)/2;
    if(x<=mid)update(L[p],L[pre],l,mid,x,val);
    else update(R[p],R[pre],mid+1,r,x,val);
}
long long query(int p,int l,int r,long long k){
    if(l==r){
        return sum[p]/cnt[p]*k;
    }
    int mid=(l+r)/2;
    if(cnt[L[p]]return sum[L[p]]+query(R[p],mid+1,r,k-cnt[L[p]]);
    else if(cnt[L[p]]==k)return sum[L[p]];
    else return query(L[p],l,mid,k);
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1,s,e,p;i<=m;i++){
        scanf("%d%d%d",&s,&e,&p);
        a[++tot].t=s,a[tot].p=p,a[tot].val=1;
        a[++tot].t=e+1,a[tot].p=p,a[tot].val=-1;
        d[i]=p;
    }
    sort(d+1,d+m+1);
    int num=unique(d+1,d+m+1)-d-1;
    for(int i=1;i<=tot;i++){
        a[i].p=lower_bound(d+1,d+num+1,a[i].p)-d;
    }
    sort(a+1,a+tot+1,cmp);
    build(T[0],1,num);
    for(int i=1;i<=tot;i++){
        while(tim<=a[i].t){
            T[tim]=T[tim-1];
            tim++;
        }
        if(!c[a[i].t]){
            c[a[i].t]=1;
            update(T[a[i].t],T[a[i].t-1],1,num,a[i].p,a[i].val);
        }
        else{
            update(T[a[i].t],T[a[i].t],1,num,a[i].p,a[i].val);
        }
//        printf("%d\n%d %lld\n",a[i].t,cnt[T[a[i].t]],sum[T[a[i].t]]);
    }
//    for(int i=1;i<=num;i++)printf("%d ",d[i]);
    for(int i=1,A,B,C,X;i<=n;i++){
        scanf("%d%d%d%d",&X,&A,&B,&C);
        long long k=1+((A*lst+B)%C);
        if(k>=cnt[T[X]])lst=sum[T[X]];
        else lst=query(T[X],1,num,k);
        printf("%lld\n",lst);
    }
    return 0;
}

 

转载于:https://www.cnblogs.com/chloris/p/11528824.html

你可能感兴趣的:(洛谷P3168 [CQOI2015]任务查询系统)