Codeforces 1199 简要题解

比赛传送门

A题

传送门
模拟
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e5+5;
int n,x,y,a[N];
inline bool check(int p){
	for(ri i=p+1,up=min(p+y,n);i<=up;++i)if(a[p]>a[i])return 0;
	for(ri i=p-1,up=max(p-x,1);i>=up;--i)if(a[p]>a[i])return 0;
	return 1;
}
int main(){
	n=read(),x=read(),y=read();
	for(ri i=1;i<=n;++i)a[i]=read();
	for(ri i=1;i<=n;++i){
		if(check(i))return cout<<i,0;
	}
	return 0;
}

B题

传送门
小学奥数题,勾股定理即可。
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=1e5+5;
int n,x,y,a[N];
inline bool check(int p){
	for(ri i=p+1,up=min(p+y,n);i<=up;++i)if(a[p]>a[i])return 0;
	for(ri i=p-1,up=max(p-x,1);i>=up;--i)if(a[p]>a[i])return 0;
	return 1;
}
int main(){
	double x=read(),y=read();
	printf("%.10lf\n",(y*y-x*x)/(2.0*x));
	return 0;
}


C题

传送门
一不小心 f s t fst fst了有点惨,计数排序+双指针即可,注意有可能爆 i n t int int需要特判。
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=4e5+5;
int n,I,a[N],b[N],m;
int main(){
	n=read(),I=read();
	for(ri i=1;i<=n;++i)a[i]=read();
	sort(a+1,a+n+1);
	int cnt=0,lim=1<<(min(20,(I*8)/n));
	
	for(ri i=1;i<=n;++i){
		if(a[i]^a[i-1])a[++cnt]=a[i],b[cnt]=1;
		else ++b[cnt];
	}
	if(cnt<=lim)return cout<<0,0;
	int sum=0,ans=0;
	for(ri i=1;i<=lim;++i)sum+=b[i];
	ans=sum;
	for(ri i=lim+1;i<=cnt;++i){
		sum-=b[i-lim],sum+=b[i];
		ans=max(ans,sum);
	}
	cout<<n-ans;
	return 0;
}

D题

传送门
大概是道线段树板题。。。
直接打全局标记+单点修改即可

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=2e5+5;
int n,a[N];
namespace sgt{
	#define lc (p<<1)
	#define rc (p<<1|1)
	#define mid (l+r>>1)
	int mn[N<<2],tg[N<<2];
	inline void pushnow(int p,int v){
		tg[p]=max(tg[p],v);
		mn[p]=max(mn[p],v);
	}
	inline void pushdown(int p){
		if(tg[p])pushnow(lc,tg[p]),pushnow(rc,tg[p]),tg[p]=0;
	}
	inline void build(int p,int l,int r){
		tg[p]=0;
		if(l==r){mn[p]=a[l];return;}
		build(lc,l,mid),build(rc,mid+1,r);
	}
	inline void modify(int p,int l,int r,int k,int v){
		if(l==r){mn[p]=v;return;}
		pushdown(p);
		k<=mid?modify(lc,l,mid,k,v):modify(rc,mid+1,r,k,v);
	}
	inline void print(int p,int l,int r){
		if(l==r){cout<<mn[p]<<' ';return;}
		pushdown(p);
		print(lc,l,mid);
		print(rc,mid+1,r);
	}
	#undef lc
	#undef rc
	#undef mid
}
int main(){
	n=read();
	for(ri i=1;i<=n;++i)a[i]=read();
	sgt::build(1,1,n);
	for(ri op,p,x,tt=read();tt;--tt){
		op=read();
		if(op==1){
			p=read(),x=read();
			sgt::modify(1,1,n,p,x);
		}
		else{
			x=read();
			sgt::pushnow(1,x);
		}
	}
	sgt::print(1,1,n);
	return 0;
}

E题

传送门
考虑对于每一条输入的边判它连着的两个点是否已经被匹配,如果没有就把它们匹配并打上标记。
最后要么匹配数 ≥ n \ge n n,要么独立集数 ≥ n \ge n n

代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=3e5+5,M=5e5+5;
int n,m,vis[N],in[N];
pii e[M];
int main(){
	for(ri tt=read();tt;--tt){
		n=read(),m=read();
		vector<int>res;
		res.clear();
		for(ri i=1,up=3*n;i<=up;++i)vis[i]=0;
		int cnt=0;
		for(ri i=1;i<=m;++i){
			e[i].fi=read(),e[i].se=read();
			if(!vis[e[i].fi]&&!vis[e[i].se])vis[e[i].fi]=vis[e[i].se]=++cnt,res.push_back(i);
		}
		if(cnt>=n){
			puts("Matching");
			for(ri i=0;i<n;++i)cout<<res[i]<<' ';
			puts("");
			continue;
		}
		res.clear();
		for(ri i=1,up=n*3;i<=up;++i)if(!vis[i])res.push_back(i);
		puts("IndSet");
		for(ri i=0;i<n;++i)cout<<res[i]<<' ';
		puts("");
	}
	return 0;
}

F题

传送门
暴力 O ( n 5 ) d p O(n^5)dp O(n5)dpBackseat-stargazer告诉了我一个 O ( n 6 ) O(n^6) O(n6)的做法然而被我叉掉了。。。
直接暴力 O ( n 5 ) d p O(n^5)dp O(n5)dp即可。
状态 f x 1 , y 1 , x 2 , y 2 f_{x_1,y_1,x_2,y_2} fx1,y1,x2,y2表示把这个矩形填满的最小代价,然后枚举横着或者竖着切开的决策即可。
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
inline int read(){
	#define gc getchar
	int ans=0;
	char ch=gc();
	while(!isdigit(ch))ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return ans;
	#undef gc
}
typedef long long ll;
typedef pair<int,int> pii;
const int mod=1e9+7;
inline int add(const int&a,const int&b){return a+b>=mod?a+b-mod:a+b;}
inline int dec(const int&a,const int&b){return a>=b?a-b:a-b+mod;}
inline int mul(const int&a,const int&b){return (ll)a*b%mod;}
inline void Add(int&a,const int&b){a=a+b>=mod?a+b-mod:a+b;}
inline void Dec(int&a,const int&b){a=a>=b?a-b:a-b+mod;}
inline void Mul(int&a,const int&b){a=(ll)a*b%mod;}
inline int ksm(int a,int p){int ret=1;for(;p;p>>=1,a=mul(a,a))if(p&1)Mul(ret,a);return ret;}
const int N=55;
int n,m,f[N][N][N][N],a[N][N];
char s[N];
inline int dfs(int x1,int y1,int x2,int y2){
	if(~f[x1][y1][x2][y2])return f[x1][y1][x2][y2];
	if(x1>x2||y1>y2)return f[x1][y1][x2][y2]=0;
	if(x1==x2&&y1==y2)return f[x1][y1][x2][y2]=a[x1][y1];
	int ret=max(x2-x1+1,y2-y1+1);
	for(ri a=x1;a<x2;++a)ret=min(ret,dfs(x1,y1,a,y2)+dfs(a+1,y1,x2,y2));
	for(ri b=y1;b<y2;++b)ret=min(ret,dfs(x1,y1,x2,b)+dfs(x1,b+1,x2,y2));
	return f[x1][y1][x2][y2]=ret;
}
int main(){
	n=read();
	for(ri i=1;i<=n;++i){
		scanf("%s",s+1);
		for(ri j=1;j<=n;++j)a[i][j]=s[j]=='#';
	}
	memset(f,-1,sizeof(f));
	cout<<dfs(1,1,n,n);
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值