UOJ Round #33 部分题目题解

比赛传送门:UOJ Round #33

A 题赛时切了。

B 题解

首先将 \(0\) 看作 \(-1\)\(1\) 看作 \(+1\),设前缀和序列为 \(b\)

\(i\) 为满足 \(b_i=y\) 的最小值,\(j\) 为满足 \(b_i=-x\) 的最小值。

如果 \(i,j\) 不存在,那么对于每一个士兵肯定攻击最近的一个敌方士兵来保证平局,因此输出 Draw。

如果 \(i,j\) 有一个不存在,那么将其设为 \(+\infty\)

\(i<j\) 那么 Aries 必胜,否则 Aqua 必胜。

考虑证明前半部分,后半部分同理。

首先对于 Aries 的士兵来说,若它们的后面有 Aqua 的士兵,那么就攻击,否则攻击 Aqua。

因为这时不存在 \(k<i\) 使 \(b_k = -x\),那么 Aqua 怎么打都是输的。

那么问题就转化为如何找到 \(i,j\),显然可以考虑放宽限制,将第一个限制改为 \(\ge\) 第二个限制改为 \(\le\),显然还是成立,直接线段树二分即可。

如果不会放宽限制,可以直接分块冲过去。

这里实现的是线段树二分。

#include<bits/stdc++.h>
#define int long long
#define double long double
using namespace std;
inline int read(){
	char c=getchar();
	int f=1,ans=0;
	while(c<48||c>57) f=(c==45?f=-1:1),c=getchar();
	while(c>=48&&c<=57) ans=(ans<<1)+(ans<<3)+(c^48),c=getchar();
	return ans*f;
}
const int N=2e5+10;
int a[N],b[N],n,m;
int t1[N<<2],t2[N<<2],add[N<<2];
#define lc k<<1
#define rc k<<1|1
inline void pushdown(int k){
	if (add[k]){
		int x=add[k];
		t1[lc]+=x,t1[rc]+=x,add[lc]+=x,add[rc]+=x,t2[lc]+=x,t2[rc]+=x;
		add[k]=0;
	}
}
void change(int k,int l,int r,int l1,int r1,int x){
	if (l1<=l&&r1>=r){add[k]+=x,t1[k]+=x,t2[k]+=x;return ;}
	int mid=l+r>>1;pushdown(k);
	if (l1<=mid) change(lc,l,mid,l1,r1,x);
	if (r1>mid) change(rc,mid+1,r,l1,r1,x);
	t1[k]=max(t1[lc],t1[rc]),t2[k]=min(t2[lc],t2[rc]);
}
int ask1(int k,int l,int r,int l1,int r1){
	if (l1==0) l1++;
	if (l1>r1) return 0;
	if (l1<=l&&r1>=r) return t1[k];
	int mid=l+r>>1,ans=-1e18;pushdown(k);
	if (l1<=mid) ans=max(ans,ask1(lc,l,mid,l1,r1));
	if (r1>mid) ans=max(ans,ask1(rc,mid+1,r,l1,r1));
	return ans;
}
int ask2(int k,int l,int r,int l1,int r1){
	if (l1<=l&&r1>=r) return t2[k];
	int mid=l+r>>1,ans=1e18;pushdown(k); 
	if (l1<=mid) ans=min(ans,ask2(lc,l,mid,l1,r1));
	if (r1>mid) ans=min(ans,ask2(rc,mid+1,r,l1,r1));
	return ans;
}
inline int get1(int l,int r,int x){
	int ans=1e18;int tmp=l;
	while(l<=r){
		int mid=l+r>>1;
		if (ask1(1,1,n,tmp,mid)>=x) ans=mid,r=mid-1;
		else l=mid+1;
	}
	return ans;
}
inline int get2(int l,int r,int x){
	int ans=1e18;int tmp=l;
	while(l<=r){
		int mid=l+r>>1;
		if (ask2(1,1,n,tmp,mid)<=x) ans=mid,r=mid-1;
		else l=mid+1;
	}
	return ans;
}
main(){
	n=read(),m=read();
	for (int i=1;i<=n;i++) scanf("%1lld",a+i);
	for (int i=1;i<=n;i++) b[i]=b[i-1]+(a[i]?-1:1),change(1,1,n,i,i,b[i]);
	while(m--){
		int op=read(),l=read();
		if (op==1){
			change(1,1,n,l,n,(a[l]?2:-2));
			a[l]^=1;
		} 
		if (op==2){
			int r=read(),x=read(),y=read();
			int i=get1(l,r,y+ask1(1,1,n,l-1,l-1)),j=get2(l,r,-x+ask1(1,1,n,l-1,l-1));
			if (i==1e18&&j==1e18) puts("Draw");
			else if (i<j) puts("Aries");
			else puts("Aqua");
		}
	}
    return 0;
}
posted @ 2026-02-04 22:07  OTn53_qwq  阅读(0)  评论(0)    收藏  举报