又是一道主席树板子题,喜闻乐见,然而我还是非常智障。
之前写的题都是单点修改区间查询,这道题变成了区间修改单点查询,然后我一度懵逼…之后发现,是不是在蓝书上学树状数组的时候,就见过类似的转化?
哦,成,差分。
完美把区间修改变成单点修改,询问的时候只需要询问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.t return 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; }