求助,暴力分类计算 WA#4,5,11,12
查看原帖
求助,暴力分类计算 WA#4,5,11,12
673643
GameFreak楼主2022/11/4 19:07

代码如下:

大概就是暴力分类的讨论用几个最值(正数最大最小、负数最大最小、0)这几个互相乘起来取最值。

我看了一下,貌似会算大,但又想不出来哪算错了。

求调

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T> inline void read(T& x);
template<typename... Args> inline void read(Args& ...args);
const int N=1e5+5;
const ll Inf=1ll*1e18+5;
int n,m,q;
ll a[N],b[N];
int lg[N];
struct st{
	ll max_[N][20],min_[N][20];
	ll _max[N][20],_min[N][20];
	bool zero[N][20];
	void init(ll* c,int len){
		for(int i=1;i<=len;i++){
			max_[i][0]=min_[i][0]=c[i];
			_min[i][0]=(c[i]>0?c[i]:Inf);
			_max[i][0]=(c[i]<0?c[i]:-Inf);
			zero[i][0]=(c[i]==0);
		}
		for(int k=1;k<=lg[len];k++){
			for(int l=1,r;(r=l+(1<<(k-1)))<=len;l++){
				max_[l][k]=max(max_[l][k-1],max_[r][k-1]);
				min_[l][k]=min(min_[l][k-1],min_[r][k-1]);
				_min[l][k]=min(_min[l][k-1],_min[r][k-1]);
				_max[l][k]=max(_max[l][k-1],_max[r][k-1]);
				zero[l][k]|=zero[l][k-1]|zero[r][k-1];
			}
		}
	}
	ll ask_max(int l,int r){
		int k=lg[r-l+1];
		return max(max_[l][k],max_[r-(1<<k)+1][k]);
	}
	ll ask_min(int l,int r){
		int k=lg[r-l+1];
		return min(min_[l][k],min_[r-(1<<k)+1][k]);
	}
	ll get_max(int l,int r){
		int k=lg[r-l+1];
		return max(_max[l][k],_max[r-(1<<k)+1][k]);
	}
	ll get_min(int l,int r){
		int k=lg[r-l+1];
		return min(_min[l][k],_min[r-(1<<k)+1][k]);
	}
	bool get_0(int l,int r){
		int k=lg[r-l+1];
		return zero[l][k]|zero[r-(1<<k)+1][k];
	}
};
st L,Q;
int main(){
	read(n,m,q);
	for(int i=2;i<=max(n,m);i++) lg[i]=lg[i>>1]+1;
	bool flag=1;
	for(int i=1;i<=n;i++) read(a[i]),flag&=(a[i]>0);
	for(int i=1;i<=m;i++) read(b[i]),flag&=(b[i]>0);
	L.init(a,n),Q.init(b,m);
	for(int l1,r1,l2,r2;q--;){
		read(l1,r1,l2,r2);
		ll ans=-Inf;
		if(flag){
			printf("%lld\n",L.ask_max(l1,r1)*Q.ask_min(l2,r2));
			continue;
		}
		if(l1==r1){
			if(a[l1]>0) ans=a[l1]*Q.ask_min(l2,r2);
			else ans=a[l1]*Q.ask_max(l2,r2);
			printf("%lld\n",ans);
			continue;
		}
		if(l2==r2){
			if(b[l2]>0) ans=b[l2]*L.ask_max(l1,r1);
			else ans=b[l2]*L.ask_min(l1,r1);
			printf("%lld\n",ans);
			continue;
		}//这上面的是判特殊情况
		if(rand()&1){//这个是迷惑行为,选择暴力
			for(int i=l1;i<=r1;i++){
				ll now=Inf;
				if(Q.get_max(l2,r2)!=-Inf) now=min(now,a[i]*Q.get_max(l2,r2));
				if(Q.get_min(l2,r2)!=Inf) now=min(now,a[i]*Q.get_min(l2,r2));
				now=min(now,a[i]*Q.ask_max(l2,r2));
				now=min(now,a[i]*Q.ask_min(l2,r2));
				if(now>ans) ans=now;
			}
			printf("%lld\n",ans);
			continue;
		}
		else{
			ll L_Up=L.ask_max(l1,r1),L_Down=L.ask_min(l1,r1);
			ll L_up=L.get_max(l1,r1),L_down=L.get_min(l1,r1);
			ll Q_Up=Q.ask_max(l2,r2),Q_Down=Q.ask_max(l2,r2);
			ll Q_up=Q.get_max(l2,r2),Q_down=Q.get_min(l2,r2);
			bool L_0=L.get_0(l1,r1),Q_0=Q.get_0(l2,r2);
			ll now=min(L_Up*Q_Up,L_Up*Q_Down);
			if(Q_up!=-Inf) now=min(now,L_Up*Q_up);
			if(Q_down!=Inf) now=min(now,L_Up*Q_down);
			if(Q_0) now=min(now,0ll);
			ans=max(ans,now);
			if(L_up!=-Inf){
				now=min(L_up*Q_Up,L_up*Q_Down);
				if(Q_up!=-Inf) now=min(now,L_up*Q_up);
				if(Q_down!=Inf) now=min(now,L_up*Q_down);
				if(Q_0) now=min(now,0ll);
				ans=max(ans,now);
			}
			now=min(L_Down*Q_Up,L_Down*Q_Down);
			if(Q_up!=-Inf) now=min(now,L_Down*Q_up);
			if(Q_down!=Inf) now=min(now,L_Down*Q_down);
			if(Q_0) now=min(now,0ll);
			ans=max(ans,now);
			if(L_down!=Inf){
				now=min(L_down*Q_Up,L_down*Q_Down);
				if(Q_up!=-Inf) now=min(now,L_down*Q_up);
				if(Q_down!=Inf) now=min(now,L_down*Q_down);
				if(Q_0) now=min(now,0ll);
				ans=max(ans,now);
			}
			if(L_0) ans=max(ans,0ll);
			printf("%lld\n",ans);
			continue;
		}
	}
	return 0;
}

template<typename T> inline void read(T& x){
	x=0;bool flag=0;char ch=getchar();
	for(;ch<'0'||ch>'9';ch=getchar()) if(ch=='-') flag=1;
	if(flag) for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)-(ch&15);
	else for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+(ch&15);
}
template<typename... Args> inline void read(Args& ...args){
	int arg[]{(read(args),0)...};
	if(0) *arg=*arg;
}
2022/11/4 19:07
加载中...