现已ac,求指出原先错误之处,感谢!
查看原帖
现已ac,求指出原先错误之处,感谢!
315205
Kniqht楼主2023/8/28 17:23
思路就是删除k个数,之后查询第x个数就等于查询第x+k个数,所以只需要记录删除数个数。记录前缀和。之后使用单调队列求最值,以二分求第x个元素

这里单调队列没问题,不需要看,就请大佬帮我看看之前的二分怎么错了,感激不尽!
#include<bits/stdc++.h> 
#define int long long
using namespace std;
const int N=2e5+10;
int T,m,n,a[N],len,s[N],q[N],l,r;
//s[]前缀和 a[]最后一个数字 q单调队列 len目前删除的个数 
int query(int x){
	x+=len; 
	int t=lower_bound(s+1,s+n+1,x)-s;
	return s[t]==x?a[t]:a[t]-s[t]+x;
}
上面是ac的,是使用lowerbound找出第一个大于等于x的数字,之后通过运算求解查询的数大小是啥

以下是错的query函数(用这个70分),是手写二分找出小于等于x但是最大的k(s[k]<=x)
int query(int x){
	x+=len; 
	int l=1,r=n;
	while(l<r){
		int mid=l+r+1>>1;
		if(s[mid]<=x) l=mid;
		else r=mid-1;
	}
	return s[l]==x?a[l]:x-s[l];
}
signed main(){
	scanf("%lld%lld",&T,&m);int opt,x;
	l=0,r=-1;
	while(m--){	
		scanf("%lld",&opt);
		if(opt==1){
			scanf("%lld",&x);
			a[++n]=x;
			s[n]=s[n-1]+a[n];
			while(l<=r&&a[q[r]]<=a[n]) r--;
			q[++r]=n;
		}
		else if(opt==2){
			scanf("%lld",&x),len+=x;
			while(l<=r&&s[q[l]]<=len) l++;
		}
		else if(opt==3) scanf("%lld",&x),printf("%lld\n",query(x));
		else printf("%lld\n",a[q[l]]);
	}
    return 0;   
}

有时候自己手写的二分就是会出现点问题,非常希望能解决这一点!

2023/8/28 17:23
加载中...