蒟蒻 WA+TLE 0 分求调
查看原帖
蒟蒻 WA+TLE 0 分求调
467089
xlsfyc楼主2022/1/29 10:28

提交记录

#include<bits/stdc++.h>
using namespace std;
const int INF=2147483647;
int n,m,t,a[100001]={0},b[100001]={0},l[1001]={0},r[1001]={0},add[1001]={0},pos[100001]={0};
void build(){//预处理 
    int num=n/t;
    if(n%t>0) num++;
    for(int i=1;i<=num;i++) l[i]=(i-1)*t+1,r[i]=i*t;
    r[num]=n;
    for(int i=1;i<=num;i++){
        for(int j=l[i];j<=r[i];j++) pos[j]=i;
        sort(a+l[i],a+r[i]+1);
    }
}
int getmax(int x,int y){//查询区间最大值 
    int p=pos[x],q=pos[y],ans=-INF;
    if(p==q){
        for(int i=x;i<=y;i++) ans=max(ans,b[i]+add[p]);
    }else{
        for(int i=p+1;i<=q-1;i++) ans=max(ans,a[r[i]]+add[i]);
        for(int i=x;i<=r[p];i++) ans=max(ans,b[i]+add[p]);
        for(int i=l[q];i<=y;i++) ans=max(ans,b[i]+add[q]);
    }
    return ans;
}
int getmin(int x,int y){//查询区间最小值 
    int p=pos[x],q=pos[y],ans=INF;
    if(p==q){
        for(int i=x;i<=y;i++) ans=min(ans,b[i]+add[p]);
    }else{
        for(int i=p+1;i<=q-1;i++) ans=min(ans,a[l[i]]+add[i]);
        for(int i=x;i<=r[p];i++) ans=min(ans,b[i]+add[p]);
        for(int i=l[q];i<=y;i++) ans=min(ans,b[i]+add[q]);
    }
    return ans;
}
int getnum(int x,int y,int d){//查询区间小于等于 d的个数 
    int p=pos[x],q=pos[y],ans=0;
    if(p==q){
        for(int i=x;i<=y;i++) if(b[i]+add[p]<=d) ans++;
    }else{
        for(int i=p+1;i<=q-1;i++) ans+=upper_bound(a+l[i],a+r[i]+1,d)-a-1;//整块 
        for(int i=x;i<=r[p];i++) if(b[i]+add[p]<=d) ans++;
        for(int i=l[q];i<=y;i++) if(b[i]+add[q]<=d) ans++;
    }
    return ans;
}
int query(int x,int y,int k){//查询区间第 k小值 
    int p=pos[x],q=pos[y];
    if(k<1 || y-x+1<k) return -1;
    int l=getmin(x,y),r=getmax(x,y),ans=-1;
    while(l<=r){//二分答案 
        int mid=(l+r)/2,cnt=getnum(x,y,mid);
        if(cnt<k) l=mid+1;
        else r=mid-1,ans=mid;
    }
    return ans;
}
void change(int x,int y,int d){//零散块暴力修改 
    int p=pos[x];
    for(int i=x;i<=y;i++) b[i]+=d;
    for(int i=l[p];i<=r[p];i++) a[i]=b[i];
    sort(a+l[p],a+r[p]+1);
}
void update(int x,int y,int d){//区间修改加上 k 
    int p=pos[x],q=pos[y];
    if(p==q) change(x,y,d);
    else{
        for(int i=p+1;i<=q-1;i++) add[i]+=d;//打懒标记 
        change(x,r[p],d),change(l[q],y,d);
    }
}
int main(){
    scanf("%d%d",&n,&m);
    t=sqrt(n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]),b[i]=a[i];//a 数组为要排序的数组,b为原数组 
    build();
    while(m--){
        int opt,l,r,k;
        scanf("%d%d%d%d",&opt,&l,&r,&k);
        if(opt==1) printf("%d",query(l,r,k));
        else update(l,r,k);
    }
    return 0;
}
2022/1/29 10:28
加载中...