「LOJ 6373」NOIP2017 普及组题目大融合

NOIP2017 普及组题目大融合

每个读者需要有某个后缀的书,可以暴力map,复杂度\(o(9*nlog(n))\),也可以反串建trie树,复杂度\(o(9*n)\)

故可以求出需要的最少的RMB数目。

显然直接求花费金币的最小值是不容易的,那么可以二分最小值。

问题变为判断性的了。

实际上S就等于一个机器人最多可以得到的RMB数...

先将行列拆开统计。

能转移到一个点的区间实际上是已知而且单调的,故可以利用单调队列来维护。

由于同种颜色的转移能多1RMB,因此每个颜色都要维护。

需要4个单调队列,复杂度$ o(n^2) $。

复杂度\(o(n^2)\)

总的复杂度$o(n^2) $,优秀。

#include<bits/stdc++.h>
#define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q)
#define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q)
#define mem(a,b) memset(a,b,sizeof a )
using namespace std;
typedef long long ll;
void in(int &r) {
	static char c;
	r=0;
	bool flag=0;
	while(c=getchar(),!isdigit(c))c=='-'&&(flag=1);
	do r=(r<<1)+(r<<3)+(c^48);
	while(c=getchar(),isdigit(c));
	flag&&(r=-r);
}
const int mn=1005;
set<int> fi;
int n,m,Q,d;
int cl[mn][mn],val[mn][mn];
ll dp[mn][mn];
ll nd;
int l_top[2],l_top1[2],r_top[2][mn],r_top1[2][mn];
int l_sta[2][mn],r_sta[2][mn][mn];
void check(ll &a,ll b) {
	if(a<b)a=b;
}
bool check(int v) {
	rep(q,1,n)rep(w,1,n)dp[q][w]=-1e18;
	rep(q,1,n)r_top[0][q]=r_top[1][q]=0,r_top1[0][q]=r_top1[1][q]=0;
	dp[1][1]=0;
	int l=max(1,d-v),r=min(n-1,d+v);
	ll ans=0;
	rep(q,1,n) {
		l_top[0]=l_top[1]=0;
		l_top1[0]=l_top1[1]=0;
		rep(w,1,n) {
			int d=cl[q][w];
			if(l_top[d]>l_top1[d])check(dp[q][w],dp[q][l_sta[d][l_top1[d]+1]]+val[q][w]+1);
			if(l_top[!d]>l_top1[!d])check(dp[q][w],dp[q][l_sta[!d][l_top1[!d]+1]]+val[q][w]);
			if(r_top[d][w]>r_top1[d][w])check(dp[q][w],dp[r_sta[d][w][r_top1[d][w]+1]][w]+val[q][w]+1);
			if(r_top[!d][w]>r_top1[!d][w])check(dp[q][w],dp[r_sta[!d][w][r_top1[!d][w]+1]][w]+val[q][w]);

			if(w-r>0) {
				d=cl[q][w-r];
				if(l_top[d]>l_top1[d]&&l_sta[d][l_top1[d]+1]==w-r)++l_top1[d];
			}
			if(q-r>0){
			    d=cl[q-r][w];
			    if(r_top[d][w]>r_top1[d][w]&&r_sta[d][w][r_top1[d][w]+1]==q-r)++r_top1[d][w];
			}
			if(w-l+1>0){
			    d=cl[q][w-l+1];
			    while(l_top[d]>l_top1[d]&&dp[q][l_sta[d][l_top[d]]]<dp[q][w-l+1])--l_top[d];
			    l_sta[d][++l_top[d]]=w-l+1;
			}
			if(q-l+1>0){
			    d=cl[q-l+1][w];
			    while(r_top[d][w]>r_top1[d][w]&&dp[r_sta[d][w][r_top[d][w]]][w]<dp[q-l+1][w])--r_top[d][w];
			    r_sta[d][w][++r_top[d][w]]=q-l+1;
			}
			ans=max(ans,dp[q][w]);
		}
	}
	return ans>=nd;
}
int main() {
	int a,b,c;
	in(n),in(m),in(Q),in(d);
	rep(q,1,m) {
		in(a);
		ll e=1;
		while(e<=a)e*=10,fi.insert(a%e);
	}

	rep(q,1,Q) {
		in(a),in(b),in(c);
		if(fi.find(b)==fi.end())nd+=c;
	}
	rep(q,1,n)rep(w,1,n)in(cl[q][w]),--cl[q][w];
	rep(q,1,n)rep(w,1,n)in(val[q][w]);
	int l=0,r=n,ans=-1;
	while(l<=r) {
		int mid=l+r>>1;
		if(check(mid))r=mid-1,ans=mid;
		else l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2019-08-05 20:46  Eeis  阅读(240)  评论(0编辑  收藏  举报