AtCoder ABC278 A-F

A - Shift

不讲。

#include<bits/stdc++.h>
using namespace std;
int n,m,a[110];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;++i) cin>>a[i];
	for(int i=m+1;i<=n;++i) cout<<a[i]<<' ';
	for(int i=n+1;i<=min(m+n,n+n);++i) cout<<0<<' ';
	cout<<endl;
	return 0;
}

B - Misjudge the Time

题目大意:若一个时间 h h : m m hh:mm hh:mm 2 × 2 2\times 2 2×2 矩阵排布,若这个时间竖着读和横着读都合法,就称这个时间是 c o n f u s i n g confusing confusing t i m e time time 。现给定某时间 h h : m m hh:mm hh:mm ,问下一个(包括这个时间) c o n f u s i n g confusing confusing t i m e time time 是多少。

简单模拟,不讲。

#include<bits/stdc++.h>
using namespace std;
bool check(int x,int y){
	if(x>=0&&x<24&&y>=0&&y<60) return 1;
	return 0;
}
int h,m;
bool vh[110][110];
int main(){
	for(int i=0;i<=9;++i)
		for(int j=0;j<=9;++j)
			for(int k=0;k<=9;++k)
				for(int l=0;l<=9;++l)
					if(check(i*10+j,k*10+l)) vh[i*10+j][k*10+l]=1;
	cin>>h>>m;
	int h1=h/10,h2=h%10,m1=m/10,m2=m%10;
	while(!vh[h1*10+m1][h2*10+m2]){
		m2++;
		if(m2==10) m1++,m2=0;
		if(m1==6) h2++,m1=0;
		if(h2==10) h1++,h2=0;
		if(h1==2&&h2==4) h1=0,h2=0;
	}
	cout<<h1*10+h2<<' '<<m1*10+m2<<endl;
	return 0;
}

C - FF

幽浮一族(确信)
题目大意:有一个无向图,有三种操作,一是建一条有向边,二是断掉一条边,三是查询两个边是否互相能够到达。这题的特殊之处是点数有 1 0 9 10^9 109 之多。

采用 m a p map map 离散。由于点数只有 1 0 9 10^9 109 ,我们可以以 m a p [ u ∗ 1 e 10 + v ] map[u*1e10+v] map[u1e10+v] 这种操作来判断道路 u → v u\to v uv 是否联通。一开始不知道 u ∗ 1 e 10 u*1e10 u1e10 这里返回值不是 u n s i g n e d unsigned unsigned l o n g long long l o n g long long ,交了三遍才过。

#include<bits/stdc++.h>
using namespace std;
unsigned long long gt=1e10;
map<unsigned long long,bool>m;
unsigned long long n,q,t,a,b;
int main(){
	cin>>n>>q;
	for(int i=1;i<=q;++i){
		cin>>t>>a>>b;
		if(t==1) m[a*gt+b]=1;
		else if(t==2) m[a*gt+b]=0;
		else{
			if(m[a*gt+b]&&m[b*gt+a]) cout<<"Yes"<<endl;
			else cout<<"No"<<endl;
		}
	}
	return 0;
}

D - All Assign Point Add

题目大意:给定一个长度为 n n n 、初值全为 0 0 0 的数组 a a a 。现有三种操作:

1. 1. 1. 将所有数改为 x x x
2. 2. 2. a p a_p ap 改为 d d d
3. 3. 3. 查询 a p a_p ap 的值。

暴力 O ( n 2 ) O(n^2) O(n2) ,不讲。

暴力线段树,不讲。

借鉴线段树懒标记思想,用 v h vh vh 数组来存每个数在一次 3 3 3 操作以后是否没有加上新的值。如果 a p a_p ap 在一次 3 3 3 操作后第一次加上新的值,就将 v h vh vh 标为 0 0 0 ,然后将 a p a_p ap 先改为上次 3 3 3 操作 x x x 的值,然后加上 d d d 。否则直接加。查询的时候,类似道理。 1 1 1 操作
只修改 x x x 值和 m e m s e t memset memset v h = 1 vh=1 vh=1 即可。

(注: 200000 200000 200000 m e m s e t memset memset 长度为 200000 200000 200000 b o o l bool bool 数组时间约 1.3 s 1.3s 1.3s ,慎用)。

#include<bits/stdc++.h>
using namespace std;
long long n,q,a[200010],as,t,ap,ad,qr;
bool vh[200010];
int main(){
	cin>>n;
	for(int i=1;i<=n;++i) cin>>a[i];
	cin>>q;
	for(int i=1;i<=q;++i){
		cin>>t;
		if(t==3){
			cin>>qr;
			if(vh[qr]) cout<<as<<endl;
			else cout<<a[qr]<<endl;
		}
		else if(t==2){
			cin>>ap>>ad;
			if(vh[ap]) a[ap]=as,vh[ap]=0;
			a[ap]+=ad;
		}
		else{
			cin>>as;
			memset(vh,1,sizeof(vh));
		}
	}
	return 0;
}

E - Grid Filling

题目大意:有一个大小 n × m n\times m n×m 的矩阵,每个格子上写着一个 ≤ k \le k k 的正整数。现在在矩阵内选择一个 r × c r\times c r×c 的矩阵删除,使得剩下的数种数最多。求最优方案下种数最大值。

简单模拟 + + + 转移优化,不讲。

#include<bits/stdc++.h>
using namespace std;
int n,m,k,r,c,a[310][310],vh[310],f[310],ans;
int main(){
	cin>>n>>m>>k>>r>>c;
	for(int i=1;i<=n;++i) for(int j=1;j<=m;++j){
		cin>>a[i][j];
		vh[a[i][j]]++;
	}
	for(int i=1;i<=n-r+1;++i){
		for(int j=1;j<=k;++j) f[j]=vh[j];
		for(int j=i;j<=r+i-1;++j) for(int l=1;l<=c;++l) f[a[j][l]]--;
		for(int j=1;j<=m-c+1;++j){
			ans=0;
			for(int l=1;l<=k;++l) if(f[l]) ans++;
			cout<<ans<<' ';
			for(int l=i;l<=r+i-1;++l) f[a[l][j]]++,f[a[l][j+c]]--;
		}
		cout<<endl;
	}
	return 0;
}

F - Shiritori

题目大意:有 ≤ 16 \le 16 16 个字符串,先手取一个,后手取一个与先手选的字符串最后一个字符为首字母的字符串,先手也选一个与后手选的字符串最后一个字符为首字母的字符串……以此类推,每个字符串只能选一次,问先手必胜还是后手必胜。

状压 d p dp dp 和博弈论板子题,不讲。

#include<bits/stdc++.h>
using namespace std;
int n,dp[100010][20][3];
vector<int>w[20];
string s[20];
int work(int zt,int ed,int cs){
	if(dp[zt][ed][cs]!=-1) return dp[zt][ed][cs];
	bool f=0,ans=0;
	for(int i=0;i<w[ed].size();++i){
		int nt=w[ed][i];
		if(!(zt&(1<<(nt-1)))) f=1,ans|=(!work(zt|(1<<(nt-1)),nt,3-cs));
	}
	if(!f) dp[zt][ed][cs]=0;
	return dp[zt][ed][cs]=ans;
}
int main(){
	cin>>n;
	memset(dp,-1,sizeof(dp));
	for(int i=1;i<=n;++i){
		cin>>s[i];
		w[0].push_back(i);
	}
	for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(s[i][s[i].size()-1]==s[j][0]) w[i].push_back(j);
	if(work(0,0,1)) cout<<"First"<<endl;
	else cout<<"Second"<<endl;
	return 0;
}

打出 6 6 6 题,总用时 77 : 28 + 20 m i n 77:28+20min 77:28+20min ,排名 877 877 877

G G G 题交互题,考试不考,不打。

E x Ex Ex 题看不懂,不打。

总结:
小细节做好,否则考试白考( 1 e 9 → u l l ? 1e9\to ull? 1e9ull?)。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值