【20431】小信抗辐射求调



我想用RMQ算法来O(1)找第一个区间最小值然后从那个最小值开始找下一个区间最小值,每一次取最小值的最大值,但是他wa50分,不知道是不是思路问题(题解给的是二分+dp)

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=200010;
void fileopen(){
	freopen("B.in","r",stdin);
	freopen("B.out","w",stdout);
}
class RMQ {
	private:
		int n,logN;vector< vector< pair<int, int> > > st;
	public:
		RMQ(const vector<int>& arr) {
			n=arr.size();
			logN=log2(n)+1;
			st.assign(logN,vector< pair<int,int> >(n));
			for(int i=0;i<n;i++){
				st[0][i]={arr[i],i};
			}
			for(int j=1;j<logN;j++){
				for (int i=0;i+(1<<j)<=n;i++){
					if(st[j-1][i].first<st[j-1][i+(1<<(j-1))].first){
						st[j][i]=st[j-1][i];
					}else{
						st[j][i]=st[j-1][i+(1<<(j-1))];
					}
				}
			}
		}
		pair<int,int> query(int left,int right){
			int j=log2(right-left+1);
			if(st[j][left].first<st[j][right-(1<<j)+1].first){
				return st[j][left];
			}else{
				return st[j][right-(1<<j)+1];
			}
		}
};
void F(){
	int n,l,r;
	scanf("%lld%lld%lld",&n,&l,&r);
	vector<int> arr(n,0);
	for(int i=0;i<n;i++){
		scanf("%lld",&arr[i]);
	}
	RMQ rmq(arr);
	int i=0,minret=rmq.query(0,n-1).first;
	while(i+r<n){
		auto result=rmq.query(i+l,i+r);
		minret=max(minret,result.first);
		i=result.second;
	}
	printf("%lld\n",minret);
}
signed main(){
	//fileopen();	
	int T;
	scanf("%lld",&T);
	while(T--){
		F();
	}
	return 0;
}

上午的普及组T2都A不了,www

这码风……

啊,原来我的码风很特殊嘛

信奥哪有人写class啊,都是struct的

我才5分,写了个神经DP

嘿嘿

难道就我暴力吗

我的评价是,不如我阚里阚气的代码awa

ME:
搜索+一点小优化=85分

我的离谱操作之bfs 顺利的5分

假设出现多个重复的最小值, 那么还需考虑取哪一个

这边给出贪心的反例
1
8 2 3
1 10 10 2 3 100 100 1
程序输出100, 但是1-10-3-1只需要10
这边再给出粗略的证明(因为本蒟蒻不会证
假设你的贪心正确
设你已经走到了点i,那么[i + 1, i + l - 1]都是你无法走到的
只要让[i + l, i + r]全部为极大值
那么程序将输出一个极大值
证明2:
显然, 这个贪心是错误的

哦,好的,蟹蟹

顺便解释一下std的思路
二分抗辐射值
然后从第一个关卡开始, 对于这个关卡可以到达的区间, 如果其中的一个未被判定的关卡的辐射值小于等于当前二分出来的抗辐射值, 则该关卡是可以到达的, 最后判断是否可以跳过n关, 统计答案并改变二分的答案区间

优先队列85分 :joy:

双端队列75pts

二分 95