其他分享
首页 > 其他分享> > Luogu P3863 序列

Luogu P3863 序列

作者:互联网

Luogu 3863 序列

solution

\(\quad\)首先考虑只有一个数,那么就建立一个时间轴,然后再在时间轴上查询即可。

\(\quad\)再回到这个题,同样建立一个时间轴。

\(\quad\)先进所有操作和询问离线处理,将操作以左端点排序,询问为时间排序。因此在查询某一个数时,将对它有过操作的区间的贡献加到时间轴上,这时候就等于专门为这个数建立了一个时间轴,这时候问题就转换为最初的问题,询问区间大于等于某数的数字个数,属于分块的基本操作。然后这个数求完后,遍历下一个数时先将之前加入到时间轴却没有对自己有过贡献的操作删掉,然后再加入新的操作区间所产生的贡献。

code

#include<bits/stdc++.h>
#define ll long long
#define double
#define fo(i,j,k) for(register int i=j;i<=k;++i)
#define fd(i,j,k) for(register int i=j;i>=k;--i)
#define ff(i,x) for(register int i=head[x];i;i=e[i].nxt)
#define fv(i,x) for(register int i=0;i<v[x].size();++i)
using namespace std;
const int N=100100;
int n,Q,c[N],cnt1,cnt2;
struct node{
 int pos,ti,val,id;
 bool operator < (const node &tt)const{
     if(pos=tt.pos) return ti<tt.ti;
     return pos<tt.pos;
 }
}a[N];
struct update{
 int l,r,val,ti;
 bool operator < (const update &t)const{
     if(l=t.l) return ti<t.ti;
     return l<t.l; 
 }
}b[N];
inline int read(){
 int ret=0,f=0;
 char ch=getchar();
 while(ch<'0' || ch>'9'){if(ch='-') f=1;ch=getchar();}
 while(ch>='0' && ch<='9') {ret=(ret<<1)+(ret<<3)+ch-(1<<4)-(1<<5);ch=getchar();} 
 return f?-ret:ret;
}
priority_queue< pair<int,int> > q;
int bl[N],sq;
ll pa[N],up[N],tag[N];
int ans[N];
void change(int l,int r,ll d){
 if(bl[l]=bl[r]){
     fo(i,l,r) up[i]+=d;
     int m=min(Q+1,bl[l]*sq);
     fo(i,(bl[l]-1)*sq+1,m) pa[i]=up[i];
     sort(pa+(bl[l]-1)*sq+1,pa+m+1);
 }
 else{
     fo(i,l,bl[l]*sq) up[i]+=d;
     fo(i,(bl[l]-1)*sq+1,bl[l]*sq) pa[i]=up[i];
     fo(i,(bl[r]-1)*sq+1,r) up[i]+=d;
     int m=min(bl[r]*sq,Q+1);
     fo(i,(bl[r]-1)*sq+1,m) pa[i]=up[i];
     sort(pa+(bl[l]-1)*sq+1,pa+bl[l]*sq+1);
     sort(pa+(bl[r]-1)*sq+1,pa+m+1);
     fo(i,bl[l]+1,bl[r]-1) tag[i]+=d;
 }
}
int cal(int x,ll y){
 int m=min(x*sq,Q+1);
 int tmp=lower_bound(pa+(x-1)*sq+1,pa+m+1,y)-pa;
 if(tmp=x*sq+1) return 0;
 tmp=x*sq-tmp+1;
 return tmp;
}
int query(int x,ll y){
 int ret=0;
 fo(i,1,bl[x]-1){
     ret+=cal(i,y-tag[i]);
 }
 fo(i,(bl[x]-1)*sq+1,x){
     if(tag[bl[i]]+up[i]>=y) ret++;
 }
 return ret;
}
int main(){
 int opt,x,y;
 n=read();Q=read();
 fo(i,1,n) c[i]=read();
 fo(i,2,Q+1){
     opt=read();
     if(opt==1){
         ++cnt2;
         b[cnt2].l=read();
         b[cnt2].r=read();
         b[cnt2].val=read();
         b[cnt2].ti=i;
     }
     else{
         ++cnt1;
         a[cnt1].pos=read();a[cnt1].val=read();
         a[cnt1].ti=i;
         a[cnt1].id=cnt1;
     }
 }
 sort(a+1,a+1+cnt1);
 sort(b+1,b+1+cnt2);
 ++n;
 sq=sqrt(n);
 fo(i,1,Q+1) bl[i]=(i-1)/sq+1;
 int now=1;
 fo(i,1,cnt1){
     while(q.size() && -q.top().first<a[i].pos){
         int xx=q.top().second;
         change(b[xx].ti,Q+1,-b[xx].val);
         q.pop();
     }
     if(a[i].pos!=a[i-1].pos){
         change(1,Q+1,c[a[i].pos]);
         change(1,Q+1,-c[a[i-1].pos]);
     }
     while(b[now].l<=a[i].pos && now<=cnt2){
         if(b[now].r<a[i].pos) {++now;continue;}
         change(b[now].ti,Q+1,b[now].val);
         q.push(make_pair(-b[now].r,now));
         now++;
     }
     ans[a[i].id]=query(a[i].ti-1,a[i].val);
 }
 fo(i,1,cnt1) printf("%d\n",ans[i]);
 return 0;
}

标签:bl,Luogu,sq,int,pa,read,序列,P3863,fo
来源: https://www.cnblogs.com/SPzos017/p/15895290.html