社区讨论

萌新分块求调有T有WA

P5356[Ynoi Easy Round 2017] 由乃打扑克参与者 2已保存回复 4

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
4 条
当前快照
1 份
快照标识符
@lo27mes2
此快照首次捕获于
2023/10/23 09:19
2 年前
此快照最后确认于
2023/11/03 09:34
2 年前
查看原帖
rt
CPP
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+5;
//#define int long long
inline int qread() {
	register char c = getchar();
	register int x = 0, f = 1;
	while (c < '0' || c > '9') {
		if (c == '-') f = -1;
		c = getchar();
	}
	while (c >= '0' && c <= '9') {
		x = (x << 3) + (x << 1) + c - 48;
		c = getchar();
	}
	return x * f;
}
int n,m,k[2005],bk,cg=1;
ll a[N],ad[2005],sum[2005],mx[2005],mi[2005];
vector<ll> B[2005];
int bl(int x){return (x-1)/bk+1;}
void remake(int k){
    while(!B[k].empty())B[k].pop_back();
    mx[k]=INT_MIN;
    mi[k]=INT_MAX;
    for(int i=(k-1)*bk+1;i<=min(n,k*(bk));i++) B[k].push_back(a[i]),mx[k]=max(mx[k],a[i]),mi[k]=min(a[i],mx[k]);
    sort(B[k].begin(),B[k].end());
}
void add(int l,int r,ll k){
    for(int i=l;i<=min(bl(l)*bk,r);i++){a[i]+=k,sum[bl(i)]+=k;}
    remake(bl(l));
    if(bl(l)!=bl(r)){
        for(int i=r;i>bk*(bl(r)-1);i--)
            a[i]+=k,sum[bl(i)]+=k;
        remake(bl(r));
    }
    for(int i=bl(l)+1;i<bl(r);i++) ad[i]+=k;
}
ll query(int l,int r,ll c){
    ll ans=0;
    for(int i=l;i<=min(bl(l)*bk,r);i++){ans+=(a[i]+ad[bl(i)]<c);}
    if(bl(l)!=bl(r)){
        for(int i=r;i>bk*(bl(r)-1);i--)
            ans+=(a[i]+ad[bl(i)]<c);
    }
    for(int i=bl(l)+1;i<bl(r);i++){
        int x=c-ad[i];
        if(mx[i]<x){ans+=bk;continue;}
        if(mi[i]>x){continue;}
        ans+=lower_bound(B[i].begin(),B[i].end(),x)-B[i].begin();
    }
    return ans;
}

ll ask(int l,int r,ll k){
	if(r-l+1<k or k<-1	) return -1;
	ll L=-2e4*cg,R=-L;
	ll ans;
	while(L<=R){
		ll mid=(L+R)>>1;
		int yzy=query(l,r,mid);
		if(yzy<=k){
			L=mid+1;
			ans=mid;
		}
		else R=mid-1;
	}
	return ans;
}

signed main(){
//	freopen("data.in","r",stdin);
//	freopen("ans.txt","w",stdout);
    n=qread(),m=qread();
    bk=sqrt(n);
    for(int i=1;i<=n;i++) a[i]=qread();
    for(int i=1;i<=bl(n);i++) remake(i);
	cg=10;
    while(m--){
        int f,l,r;ll k;
        f=qread(),l=qread(),r=qread(),k=qread();
        if(f==2) add(l,r,k),cg++;
        else printf("%lld\n",ask(l,r,k));
    }
}

回复

4 条回复,欢迎继续交流。

正在加载回复...