GDKOI-S 2024 Day2T1 不休陀螺

现场做了,离散化数组没开 ll,被卡 au 线 卡线 ag。

因为代码是半个月前写的了,回忆做法时可能有点偏差,如果发现有误请联系我修改。😃

考虑怎么刻画题目所给条件。发现对于一个区间 [l,r],可以钦定其中一个卡牌 i,使得这张卡牌是第一张无法打出的牌。然后考虑它前面放什么牌,会发现前面会放所有 ai>bi 的牌。

然后用形式化语言刻画可以无限取下去的条件。设 ci=aibi,则一个区间可行,可以分成两种情况。

  • 钦定的牌 aibi 时,i,Ej[l,r]cj>0cj<ai

  • 否则,i,Ej[l,r]cj>0cj+aibi<aiEj[l,r]cj>0cj<bi

  • 任何情况下,i[l,r]ci0,否则一定无法无限取。

感性与理性并用地理解容易发现前面两个限制是满足单调性的,原因显然。于是想到固定右端点 r,二分 l。但是又有一个问题:因为 ci 不一定非负,所以这些所有限制并不是满足单调性的。于是考虑对于每个右端点,求出极大区间 [Li,Ri],再用前缀和 si=jicj 转化一下第三个限制,则一个区间 [l,r] 符合条件的限制条件变成:

LrlRrsrsl1

这显然是一个二维数点问题,扫描线解决。时间复杂度 O(nlogn)

code:

点击查看代码
bool Mbe;
int n,m,a[N],b[N];
ll s[N],A[N],B[N],d[N];
vector<int> g[N];
struct STable{
	int st[2][N][23],lg[N],pw[107];
	void init(){
		rep(i,1,n){
			st[0][i][0]=st[1][i][0]=-inf;
			if(a[i]>b[i])st[0][i][0]=b[i];
			else st[1][i][0]=a[i];
		}
		rep(i,2,n)lg[i]=lg[i>>1]+1;
		rep(i,0,30)pw[i]=1<<i;
		rep(j,1,lg[n]){
			rep(i,1,n-pw[j]+1){
				rep(k,0,1)st[k][i][j]=max(st[k][i][j-1],st[k][i+pw[j-1]][j-1]);
			}
		}
	}
	il int qryMax(int l,int r,int p){
		int k=lg[r-l+1];
		return max(st[p][l][k],st[p][r-pw[k]+1][k]);
	}
}T;
struct BIT{
	int tr[N];
	#define lb(x) (x&(-x))
	il void upd(int x,int y){while(x<=n)tr[x]+=y,x+=lb(x);}
	il int qry(int x){int ret=0;while(x)ret+=tr[x],x-=lb(x);return ret;}
	#undef lb
}R;
il bool check(int l,int r){
	if(T.qryMax(l,r,1)>m-s[r]+s[l-1])return 0;
	if(T.qryMax(l,r,0)>m-s[r]+s[l-1])return 0;
	return 1;
}
void Yorushika(){
	scanf("%d%d",&n,&m);
	rep(i,1,n)a[i]=read(),A[i]=A[i-1]+a[i];
	rep(i,1,n)b[i]=read(),B[i]=B[i-1]+b[i];
	rep(i,1,n){
		s[i]=s[i-1];
		if(a[i]>b[i])s[i]+=a[i]-b[i];
	}
	T.init();
	rep(i,1,n)d[i]=A[i]-B[i];
	d[n+1]=0;
	sort(d+1,d+n+2);
	int k=unique(d+1,d+n+2)-d-1;
	rep(i,1,n){
		int l=1,r=i,res=i+1;
		while(l<=r){
			int mid=(l+r)>>1;
			if(check(mid,i))r=(res=mid)-1;
			else l=mid+1;
		}
		int p=lower_bound(d+1,d+k+1,A[i]-B[i])-d;
		g[res-1].eb(p);
	}
	R.upd(lower_bound(d+1,d+k+1,0)-d,1);
	ll ans=0;
	rep(i,1,n){
		int p=lower_bound(d+1,d+k+1,A[i]-B[i])-d;
		for(int j:g[i])ans-=i-R.qry(j-1);
		ans+=i-R.qry(p-1),R.upd(p,1);
	}
	printf("%lld\n",ans);
}
bool Med;
signed main(){
	freopen("top.in","r",stdin);
	freopen("top.out","w",stdout);
	int t=1;
//	scanf("%d",&t);
	while(t--)Yorushika();
//	cerr<<1.*(&Mbe-&Med)/1024/1024;
}
posted @   yinhee  阅读(19)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话

阅读目录(Content)

此页目录为空

点击右上角即可分享
微信分享提示