社区讨论

90pts求调

P14507缺零分治 mexdnc参与者 2已保存回复 2

讨论操作

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

当前回复
2 条
当前快照
1 份
快照标识符
@mi0ve79m
此快照首次捕获于
2025/11/16 06:40
4 个月前
此快照最后确认于
2025/11/17 09:13
4 个月前
查看原帖
WA on1,2
CPP
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+5;

struct number{
	ll a,b;
}p[N]; 
ll pre[N],cnt[N];
const ll M=1e18+2; 
int pos;
ll f(ll x) {
	ll l=1,r=pos,mid,ans=0;
	while(l<=r){
		mid=(l+r)/2;
		if(pre[mid]>=x){
			ans=mid;
			l=mid+1;
		}else{
			r=mid-1;
		}
	}
	return ans;
}

void work(){
	ll n,q;
	scanf("%lld%lld",&n,&q);
	pos=n+1;
	for(int i=1;i<=n;i++){
		scanf("%lld%lld",&p[i].a,&p[i].b);
	}
	if(n==1) {
		if(p[1].a==0){
			for(;q;q--){
				ll m;
				scanf("%lld",&m);
				if(m==0) printf("-1\n");
				else if(m<=p[1].b) printf("%lld\n",m);
				else printf("-1\n");
			}
		}else{
			for(;q;q--){
				ll m;
				scanf("%lld",&m);
				if(m==0) printf("1\n");
				else printf("-1\n");
			}
		}
		return;
	}
	ll mex=0;
	
	for(int i=1;i<=n+5;i++) {
		if(p[i].a!=(i-1)){
			pos=i;
			mex=i-1;
			break;
		}
	}
//	printf("%d\n",mex);
//	p[1].b--;
	for(int i=2;i<=n+5;i++) {
		if(p[i].a!=(i-1)){
			pos=i;
			break;
		} 
		p[i].b=min(p[i].b,p[i-1].b);
//		p[i].b--; 
	}
//	for(int i=1;i<=n;i++) p[i].b--;
//	for(int i=1;i<=n;i++) {
//		printf("%lld ",p[i].b);
//	}
	p[pos].b=0;
	pre[pos]=cnt[pos]=0;
//	pre[pos]=mex;
	for(int i=pos-1;i>=1;i--){
		ll c= p[i].b-p[i+1].b;
		pre[i]=pre[i+1]+c*i;
		cnt[i]=cnt[i+1]+c;
		pre[i]=min(pre[i],M+10);
//		pre[i]=min(pre[i],1e18+1);
	}
//	for(int i=1;i<=pos;i++) {
//		printf("%lld ",pre[i]);
//	}
//	printf("%lld\n",mex) ;
	for(;q;q--) {
		ll m;
		scanf("%lld",&m);
		if(mex==0){
			if(m>0) printf("-1\n");
			else printf("1\n");
		}else{
			if(m==0) printf("-1\n");
			else if(m<mex) {
				printf("2\n");
			}else if(m==mex){
				printf("1\n");
			}else if(m>pre[1]){
				printf("-1\n");
			}else{
				ll t=f(m);
				while(pre[t+1]>m && t<pos) t++;
//				printf("%lld\n",t) ;
				ll v=(m-pre[t+1])/t;
				if((m-pre[t+1])%t!=0) v++;
				printf("%lld\n",cnt[t+1]+v);
			}
		}
	}
}

int main(){
//	printf("%lld\n",M+10); 
//	system("fc mexdnc2.out mexdnc.out") ;
//	freopen("mexdnc2.in","r",stdin);
//	freopen("mexdnc.out","w",stdout);
	int T;
	scanf("%d",&T) ;
	for(;T;T--) work();
	return 0; 
}
/*

算出一整个的mex

若mex不为0 
m<mex则需要一个垃圾桶 答案为2 
m=0 无解

m>mex则需要开出新集合

从高到低依次贪心(无需开新桶,因为可以放进另一个桶)
二分出位置,计算 

*/

回复

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

正在加载回复...