cf1199解题报告

cf1199解题报告

发一波水题。

A

模拟

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int _=1e6+7;
int n,x,y,a[_];
int main() {
	scanf("%d%d%d",&n,&x,&y);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	for(int d=1;d<=n;++d) {
		int flag=0;
		for(int j=max(1,d-x);j<d;++j)
			if(a[d]>=a[j]) flag=1;
		for(int j=d+1;j<=min(n,d+y);++j)
			if(a[d]>=a[j]) flag=1;
		if(!flag) return printf("%d
",d),0;
	}
	return 0;
}

B

小学几何题。输出lf格式不对错了几发、、、

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int _=1e6+7;
double H,L,x;
int main() {
	cin>>H>>L;
	double x=(H*H+L*L)/(2*H);
	printf("%.13lf
",x-H);
	return 0;
}

C

最多能保留几个不同的数,然后删就行了。
我以为是(map)(log)太大了T了。
其实是暴利统计最多保留几个没加范围。

#include <bits/stdc++.h>
using namespace std;
const int _=4e5+7;
int n,m,k,a[_],ans=0x3f3f3f3f;
int Hash[_],lsh[_];
vector<pair<int,int> > tmp;
int sum[_];
int read() {
	int x=0,f=1;char s=getchar();
	for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1;
	for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0';
	return x*f;
}
int main() {
	n=read(),m=read()*8;
	for(int i=1;i<=n;++i) lsh[i]=a[i]=read();
	sort(lsh+1,lsh+1+n);
	int len=unique(lsh+1,lsh+1+n)-lsh-1;
	for(int i=1;i<=n;++i) a[i]=lower_bound(lsh+1,lsh+1+len,a[i])-lsh;
	for(int i=1;i<=n;++i) Hash[a[i]]++;
	while((int)ceil(log2(k+1))*n<=m&&k<=n) k++;
	for(int i=1;i<=n;++i)
		if(Hash[i]) tmp.push_back(make_pair(i,Hash[i]));
	int Siz=tmp.size();
	for(int i=0;i<Siz;++i) {
		if(i) sum[i]=sum[i-1];
		sum[i]+=tmp[i].second;
		if(i<k) ans=min(ans,n-sum[i]);
		else ans=min(ans,n-sum[i]+sum[i-k]);
	}
 	printf("%d
",ans);
	return 0;
}

D

每个数最后的值=max(上一次更改的值,这段时间内政府补贴的最大值)。
由于都是后缀,(O(n))统计一遍就行了。
当然也可以学傻了写线段树或者BIT。

#include <bits/stdc++.h>
using namespace std;
const int _=4e5+7;
namespace seg {
	#define ls rt<<1
	#define rs rt<<1|1
	int a[_],ma[_<<2];
	void build(int l,int r,int rt) {
		if(l==r) {ma[rt]=a[l];return;}
		int mid=(l+r)>>1;
		build(l,mid,ls);
		build(mid+1,r,rs);
		ma[rt]=max(ma[ls],ma[rs]);
	}
	int modify(int L,int R,int l,int r,int rt) {
		if(L>R) return 0;
		if(L<=l&&r<=R) return ma[rt];
		int mid=(l+r)>>1,ma=0;
		if(L<=mid) ma=max(ma,modify(L,R,l,mid,ls));
		if(R>mid) ma=max(ma,modify(L,R,mid+1,r,rs));
		return ma;
	}
}
int n,a[_],las[_],q,dsr[_];
int main() {
	// freopen("a.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i) scanf("%d",&a[i]);
	scanf("%d",&q);
	for(int i=1,opt,p,x;i<=q;++i) {
		scanf("%d",&opt);
		if(opt==1) scanf("%d%d",&p,&x),las[p]=i,dsr[i]=x;
		else scanf("%d",&x),seg::a[i]=x;
	}
	seg::build(1,q,1);
	for(int i=1,val;i<=n;++i) {
		if(!las[i]) val=a[i];
		else val=dsr[las[i]];
		val=max(val,seg::modify(max(las[i],1),q,1,q,1));
		printf("%d ",val);
	}
	return 0;
}

E

(matching)(indset)至少存在一个。
每次遇到符合(matching)的边就加上。
做完后,剩下的点就是(indset)的。
反证:没在(matching)的两个点,而且有边相连,显然矛盾。
因为是(3n)个点,所以做完后一定有一个满足条件。

#include <bits/stdc++.h>
using namespace std;
const int _=5e5+7;
int T,n,m,vis[_];
std::vector<int> dsr;
int main() {
	scanf("%d",&T);
	while(T --> 0) {
		scanf("%d%d",&n,&m);
		dsr.clear();
		for(int i=1;i<=3*n;++i) vis[i]=0;
		for(int i=1,u,v;i<=m;++i) {
			scanf("%d%d",&u,&v);
			if(!vis[u]&&!vis[v]) {
				vis[u]=vis[v]=1;
				dsr.push_back(i);
			}
		}
		if((int)dsr.size()>=n) {
			printf("Matching
");
			for(int i=0;i<n;++i) printf("%d ",dsr[i]);
			printf("
");
		} else {
			printf("IndSet
");
			for(int i=1,js=1;js<=n;++i)
				if(!vis[i]) printf("%d ",i),++js;
			printf("
");
		}
	}
	return 0;
}

F

大爆搜
(f[x][y][X][Y])表示左上角((x,y)),右下角((X,Y))的矩阵变为白色的最小代价。
每次转移(O(n)),有(O(n^4))个转态。复杂度(O(n^5))

#include <bits/stdc++.h>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int _=51;
int n,s[_][_],num[_][_],f[_][_][_][_];
char S[_][_];
int calc(int x,int y,int X,int Y) {
	return s[X][Y]-s[x-1][Y]-s[X][y-1]+s[x-1][y-1];
}
int dfs(int x,int y,int X,int Y) {
	if(!calc(x,y,X,Y)||f[x][y][X][Y]) return f[x][y][X][Y];
	if(x==X&&y==Y) {f[x][y][X][Y]=1;return 1;}
	f[x][y][X][Y]=max(X-x+1,Y-y+1);
	for(int i=x;i<X;++i)
		f[x][y][X][Y]=min(f[x][y][X][Y],dfs(x,y,i,Y)+dfs(i+1,y,X,Y));
	for(int i=y;i<Y;++i)
		f[x][y][X][Y]=min(f[x][y][X][Y],dfs(x,y,X,i)+dfs(x,i+1,X,Y));
	return f[x][y][X][Y];
}
int main() {
	freopen("a.in","r",stdin);
	scanf("%d",&n);
	for(int i=1;i<=n;++i) {
		scanf("%s",S[i]+1);
		for(int j=1,tot=0;j<=n;++j) {
			tot+=(S[i][j]=='#');
			s[i][j]=s[i-1][j]+tot;
		}
	}
	printf("%d
",dfs(1,1,n,n));
	return 0;
}
原文地址:https://www.cnblogs.com/dsrdsr/p/11372863.html