20191004 「HZOJ NOIP2019 Round #9」20191004模拟

综述

第一次 rk1 ,激动。

题目是 COCI 18/19 Round #1 的三至五题。

得分 \(100+100+20\)


\(\mathrm{cipele}\)

问题描述

HZOJ1313

题解

二分答案+贪心

发现“最大值最小”,自然想到二分答案。

\(a,b\) 排序,通过一些操作保证 \(a\)\(b\) 短。

如果 \(b_j\) 不能被 \(a_i\) 选择,那么它一定不能被 \(a_k(k>i)\) 选择。

基于这个贪心配对即可。

\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

void read(int &x){
	x=0;char ch=1;int fh;
	while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
	if(ch=='-') ch=getchar(),fh=-1;
	else fh=1;
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=fh;
}

const int maxn=100000+7;
const int INF=0x3f3f3f3f;

int n,m,mxa=-INF,mia=INF,mxb=-INF,mib=INF;
int a[maxn],b[maxn];

int l,r,mid,ans;

bool check(){
	int j=1;bool eps;
	for(int i=1;i<=n;i++){
		eps=0;
		for(;j<=m;j++){
			if(abs(a[i]-b[j])<=mid){
				++j;eps=1;break;
			}
		}
		if(!eps) return false;
	}
	return true;
}

void deal(){
	for(int i=1;i<=n;i++) swap(a[i],b[i]);
	swap(n,m);
}

int main(){
	freopen("cipele.in","r",stdin);freopen("cipele.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;i++) read(a[i]),mxa=max(mxa,a[i]),mia=min(mia,a[i]);
	for(int i=1;i<=m;i++) read(b[i]),mxb=max(mxb,b[i]),mib=min(mib,b[i]);
	if(n>m) deal();
	sort(a+1,a+n+1);sort(b+1,b+m+1);
	l=0,r=max(abs(mxa-mib),abs(mxb-mia));
	while(l<=r){
		mid=(l+r)>>1;
		if(check()){
			ans=mid;r=mid-1;
		}
		else l=mid+1;
	}
	printf("%d\n",ans);
	return 0;
}

\(\mathrm{strah}\)

问题描述

HZOJ1314

题解

单调栈维护最大矩形

打表找规律

\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

#define int long long

void read(int &x){
	x=0;char ch=1;int fh;
	while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
	if(ch=='-') ch=getchar(),fh=-1;
	else fh=1;
	while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
	x*=fh;
}

void fr(int &x){
	char ch=1;
	while(ch!='.'&&ch!='#') ch=getchar();
	if(ch=='.') x=0;
	else x=1;
}

const int maxn=2000+7;

int sta[maxn],top;
int n,m,a[maxn][maxn];

int lft[maxn],rgt[maxn];
int tmp[maxn];

int ans;

int solve(int j){
	int a=j-lft[j]+1,b=rgt[j]-j+1;
	return a*(a+1)/2*b+b*(b+1)/2*a-a*b;
}

signed main(){
	freopen("strah.in","r",stdin);freopen("strah.out","w",stdout);
	read(n);read(m);
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			fr(a[i][j]);
		}
	}
	for(int i=1;i<=n;i++){
		top=0;
		for(int j=1;j<=m;j++){
			if(!a[i][j]) tmp[j]++;
			else tmp[j]=0;
			while(top&&tmp[sta[top]]>tmp[j]){
				rgt[sta[top]]=j-1;--top;
			}
			lft[j]=sta[top]+1;
			sta[++top]=j;
		}
		while(top) rgt[sta[top--]]=m;
		for(int j=1;j<=m;j++){
			ans=ans+tmp[j]*(tmp[j]+1)*solve(j)/2;
		}
	}
	printf("%lld\n",ans);
	return 0;
}

\(\mathrm{teoreticar}\)

问题描述

HZOJ1315

题解

只会暴力

暴力染色,判断是否可行

这样貌似求出来的就是 \(C\) .

posted @ 2019-10-04 21:16  览遍千秋  阅读(168)  评论(0编辑  收藏  举报