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[u∗1e10+v] 这种操作来判断道路 u → v u\to v u→v 是否联通。一开始不知道 u ∗ 1 e 10 u*1e10 u∗1e10 这里返回值不是 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?
1e9→ull?)。