洛谷P3863 序列(离线+分块)

传送门
最直观的想法是维护N个元素每个时间的状态.这个做法显然不切实际,但似乎在线去做又没有什么很好的办法,所以只能考虑离线.
离线做法:因为只有单点查询,所以我们可以按照每个修改和询问的位置排序.然后只维护每个时间点的状态.修改可以拆分成两个操作,在l位置上修改time-m的值,在r+1位置撤销这次修改.然后离线的一个一个处理询问就可以了.而询问可以转化成1-time-1有多少个数>=y-a[pos].这个可以用分块来处理.对每个块排序然后跨块的时候二分就可以了.

#define LL long long
#define pq priority_queue
#define ULL unsigned long long
#define pb push_back
#define mem(a,x) memset(a,x,sizeof a)
#define pii pair<int,int>
#define fir(i,a,b) for(int i=a;i<=(int)b;++i)
#define afir(i,a,b) for(int i=(int)a;i>=b;--i)
#define ft first
#define vi vector<int>
#define sd second
#define ALL(a) a.begin(),a.end()
#define bug puts("-------")
#define mpr(a,b) make_pair(a,b)
#include <bits/stdc++.h>

using namespace std;
const int N = 2e5+10;

inline void read(int &a){
    
    
    int x = 0,f=1;char ch = getchar();
    while(ch<'0'||ch>'9'){
    
    if(ch=='-')f=-1;ch=getchar();}
    while(ch<='9'&&ch>='0'){
    
    x=x*10+ch-'0';ch=getchar();}
    a = x*f;
}
struct C{
    
    
    int p,x,tim;
}c[N];
struct Q{
    
    
    int p,x,tim,id;
}q[N];
int n,m,blo,num,L[N],R[N],pos[N],a[N],ans[N],siz[N];
LL t[N],v[N],tag[N];
void build(){
    
    
    int n = m+1;
    blo = sqrt(n);
    num = n/blo;
    fir(i,1,num){
    
    
        L[i] = (i-1)*blo+1;
        R[i] = i*blo;
    }
    if(n % blo){
    
    
        num++;
        L[num] = R[num-1]+1;
        R[num] = n;
    }
    fir(i,1,num){
    
    
    	siz[i] = tag[i] = 0;
        fir(j,L[i],R[i]){
    
    
            pos[j] = i;
            t[j] = v[j] = 0;
        	siz[i]++;
        }
    }
}
bool c1(Q a,Q b){
    
    
    return a.p == b.p?a.tim<b.tim:a.p<b.p;
}
bool c2(C a,C b){
    
    
    return a.p == b.p?a.tim<b.tim:a.p<b.p;
}
void clr(int i){
    
    
    if(tag[i]){
    
    
        fir(j,L[i],R[i]) t[j] += tag[i];
        tag[i] = 0;
    }
}
void change(int l,int r,int x){
    
    
    int p = pos[l],q = pos[r];
    if(p == q){
    
    
        clr(q);
        fir(i,l,r) t[i] += x;
        fir(i,L[q],R[q]) v[i] = t[i];
        sort(v+L[p],v+R[p]+1);
    }
    else{
    
    
        fir(i,p+1,q-1) tag[i] += x;
        clr(p);clr(q);
        fir(i,l,R[p]) t[i] += x;
        fir(i,L[q],r) t[i] += x;
        fir(i,L[p],R[p]) v[i] = t[i];
        fir(i,L[q],R[q]) v[i] = t[i];
        sort(v+L[p],v+R[p]+1);sort(v+L[q],v+R[q]+1);
    }
}
int query(int l,int r,LL x){
    
    
    int p = pos[l],q = pos[r],res = 0;
    if(p == q){
    
    
        clr(p);
        fir(i,l,r) if(t[i] >= x) res++;
        fir(i,L[q],R[q]) v[i] = t[i];
        sort(v+L[p],v+R[p]+1);
    }
    else{
    
    
        clr(p);clr(q);
        fir(i,l,R[p]) if(t[i] >= x) res++;
        fir(i,L[q],r) if(t[i] >= x) res++;
        fir(i,L[q],R[q]) v[i] = t[i];
        fir(i,L[p],R[p]) v[i] = t[i];
        sort(v+L[p],v+R[p]+1);sort(v+L[q],v+R[q]+1);
        fir(i,p+1,q-1){
    
    
            LL cur = x-tag[i];
            int p = lower_bound(v+L[i],v+R[i]+1,cur)-v;
            res += (siz[i] - p + L[i]);
        }
    }
    return res;
}
int main(){
    
    
    read(n);read(m);
    int t1=0,t2=0;
    fir(i,1,n) read(a[i]);
    fir(i,1,m){
    
    
        int op;
        read(op);
        if(op == 1){
    
    
            int l,r,x;
            read(l);read(r);read(x);
            ++t1;c[t1].p = l;c[t1].x = x;c[t1].tim = i+1;
            ++t1;c[t1].p = r+1;c[t1].x = -x;c[t1].tim = i+1;
        }
        else++t2,read(q[t2].p),read(q[t2].x),q[t2].tim=i+1,q[t2].id = t2;
    }
    sort(c+1,c+1+t1,c2);
    sort(q+1,q+1+t2,c1);
    build();
    int j = 1;
    fir(i,1,t2){
    
    
        while(j <= t1 && (c[j].p < q[i].p || (c[j].p == q[i].p && c[j].tim < q[i].tim))) change(c[j].tim,m+1,c[j].x),j++; 
        ans[q[i].id] = query(1,q[i].tim-1,q[i].x-a[q[i].p]);
    }
    fir(i,1,t2)
        printf("%d\n",ans[i]);
    
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_45590210/article/details/108901466