codeforces 859 div4

A

题目

签到题,没有算法,纯if判断然后输出

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;

int t,a,b,c;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >> a >> b >> c;
if(a+b == c) cout << "+" <<'\n';
else cout << "-" <<'\n';
}
return 0;
}

B

题目

此题贪心,题目简述就是偶数之和大于级数之和就行,难度也是签到的难度

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#include <bits/stdc++.h>
using namespace std;

int ou=0,ji=0,a,t,n;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >>n;
for(int j=0;j<n;j++){
cin >>a;
if(a%2==0) ou +=a;
else ji += a;
}
if(ou>ji) cout<<"YES"<<'\n';
else cout << "No"<<'\n';
ji=0;ou=0;
}
return 0;
}

C

题目

模拟题,字符串处理。此题题意是给你一串字符串,你可以把同种的所有字母都用1或0来代替,问你能不能形成像0101010这种1和0交替出现的形式。用Hash数组来记录字符串中某个字母是否已经被替换,然后判断就行

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;

string s;
char cha;
int t,n,Hash[101][2001],pd;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >>t;
for(int i=0;i<t;i++){
cin >> n;cin>>s;
fill_n(&Hash[0][0],101*2001,-1);
for(int j=0;j<n;j++){
if(Hash[t][j] != -1) continue;
if(j!=n-1 && s[j]==s[j+1]){
pd=1;break;
}
else{
cha =s[j];
Hash[t][j]=j%2;
s[j]='0';
auto it =s.find(cha);
while(it != string::npos){
Hash[t][it]=j%2;
s[it]='0';
it = s.find(cha);
}
}
}
for(int j=0;j<n-1;j++){
if(Hash[t][j] == Hash[t][j+1]){
pd=1;break;
}
}
if(pd==0) cout << "YES" <<endl;
else cout << "NO" << endl;
pd=0;
}
return 0;
}

D

题目

此题题意为给你一个整数数组,把其中a[left]到a[right]都替换为k,问你数组元素之和是否为奇数。我第一遍直接暴力速度解决,结果TLE,发现n和q数据太大了,明显不是让我暴力的。因此改用前缀和解决

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <bits/stdc++.h>
using namespace std;

long long t,n,q,l,r,k,a[200001],cache,sum=0;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
for(int i=0;i<t;i++){
cin >> n >> q;
for(int j=0;j<n;j++){
cin >> cache;
a[j] = cache;
}
for(int j=1;j<n;j++) a[j]+=a[j-1];
for(int j=0;j<q;j++){
cin >> l >> r >> k;
if(l>1) sum = a[l-2] + a[n-1]-a[r-1] + (r-l+1)*k;
else sum = a[n-1]-a[r-1] + (r-l+1)*k;
if(sum %2 ==1) cout << "YES" <<'\n';
else cout << "NO" << '\n';
sum=0;
}
}
return 0;
}

E

题目

题干非常长,快有我长了,有点像猜数字的升级版,主要用二分来做

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
#include <bits/stdc++.h>
using namespace std;

int t,n,a[200001],ai,weight=0,weight_in,special,inter,l,r,left=1;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin>>n;
for(int i=0;i<n;i++){
cin>>ai;
a[i]=ai;
}
l=1;r=(l+n)/2;weight=0;
while(1){
cout<<"?"<<' '<<r-l+1<<' ';
for(int i=l;i<=r;i++){
cout<<i<<' ';
weight+=a[i-1];
}cout<<endl;
cin >> weight_in;
if(weight!=weight_in && r==l ){
special=l;break;
}
if(weight == weight_in) {
if(l+1==n){
special=n;break;
}
if(r+1<=n) l=r+1;
else l=r;
r=(l+n)/2;

}else{
n=r;
r=(l+r)/2;
}
weight=0;
}
cout<<"!"<<' '<<special<<endl;
}
return 0;
}

F

题目

这道是这套里最难的题,主要是dfs,一个小球沿着斜线一直跑,碰到墙就转向,碰到墙角就反弹,问你能不能经过某一点。这题的行和列最大都为25000,如果直接room[25000][25000],那么25000250004/1024/1024/1024=2.3GB 会爆栈,改用单独的行和列变量来判断。

初始思路:用dfs双头搜,两次搜索都是碰到墙角就结束,因为两个墙角构成一个死循环,同时判断不撞墙角的死循环的特殊情况,构成四边形死循环也结束。这个思路没有全部AC,从下午调到第二天下午,恼火,然后换了个思路。

AC思路:一个格子有四个方向,一共有nm个格子,所以小球至多走nm*4步,如果超过这个数必然是死循环,结束。

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#include <bits/stdc++.h>
using namespace std;

int pd = 0, times = 0, room, t, n, m, i1, j_1, i2, j2;
string d;
struct zb {
int x; int y;
bool operator==(const zb& other) const {
return x == other.x && y == other.y;
}
}Next;
map <string, zb> direction;
#define checkx (Next.x>0 && Next.x<=n)
#define checky (Next.y>0 && Next.y<=m)
#define qiangjiao (Next.x<1 && Next.y<1 || Next.x<1 && Next.y>m || Next.x>n && Next.y<1 || Next.x>n && Next.y>m)
void dfs(int dx, int dy, string& d, int& times) {
if (dx == i2 && dy == j2) {
pd = 1; return;
}
Next.x = dx + direction[d].x;
Next.y = dy + direction[d].y;
if (times>room) return;
if (qiangjiao) {
times++;
if (d == "UL") { d = "DR"; Next.x = dx; Next.y = dy; }
else if (d == "UR") { d = "DL"; Next.x = dx; Next.y = dy; }
else if (d == "DR") { d = "UL"; Next.x = dx; Next.y = dy; }
else if (d == "DL") { d = "UR"; Next.x = dx; Next.y = dy; }
}
else if (Next.x < 1 && checky) {
times++;
if (d == "UL") {
d = "DL"; Next.x = dx; Next.y = dy;
}
if (d == "UR") {
d = "DR"; Next.x = dx; Next.y = dy;
}
}
else if (Next.x > n && checky) {
times++;
if (d == "DR") {
d = "UR"; Next.x = dx; Next.y = dy;
}
if (d == "DL") {
d = "UL"; Next.x = dx; Next.y = dy;
}
}
else if (checkx && Next.y < 1) {
times++;
if (d == "UL") {
d = "UR"; Next.x = dx; Next.y = dy;
}
if (d == "DL") {
d = "DR"; Next.x = dx; Next.y = dy;
}
}
else if (checkx && Next.y > m) {
times++;
if (d == "UR") {
d = "UL"; Next.x = dx; Next.y = dy;
}
if (d == "DR") {
d = "DL"; Next.x = dx; Next.y = dy;
}
}
dfs(Next.x, Next.y, d, times);
}
int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
direction["UL"] = { -1,-1 };
direction["UR"] = { -1,1 };
direction["DR"] = { 1,1 };
direction["DL"] = { 1,-1 };
cin >> t;
while (t--) {
cin >> n >> m >> i1 >> j_1 >> i2 >> j2 >> d;
room = n * m * 4;
dfs(i1, j_1, d,times);
if (pd) cout << times << '\n';
else cout << -1 << '\n';
times = 0; pd = 0;
}
return 0;
}

codeforces 950 div3

A

题目

难度比较低,字符串处理

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <bits/stdc++.h>
using namespace std;

string zimu[7]={"A","B","C","D","E","F","G"},inp,cha;
int t,n,m,haxi[51],sum=0;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n >> m >> inp;
while(m--){
for(int i=0;i<7;i++){
cha=zimu[i];
int it = inp.find(cha);
if(it == -1) sum++;
else inp[it]='0';
}
}
cout<<sum<<'\n';
sum=0;inp.clear();
}
return 0;
}

B

题目

这题考排序,不难,就是特判有点多

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
#include <bits/stdc++.h>
using namespace std;

int t,n,f,k,fav,cache;
vector <int> a;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n >> f >> k;
for(int i=0;i<n;i++){
cin >> cache;
a.push_back(cache);
}
fav = a[f-1];
sort(a.begin(),a.end(),greater<int>());
if(a[k-1]<fav) cout << "YES" <<'\n';
else if(a[k-1]>fav) cout << "NO" <<'\n';
else if(n==1) cout << "YES" <<'\n';
else if(k<n && a[k]==fav) cout << "MAYBE" <<'\n';
else cout << "YES" <<'\n';
a.clear();
}
return 0;
}

C

题目

(这道题居然有156个test!)

题意大概是给你一个初始数组a,和现在的数组b,问你在m次变换(把a[c]赋值为d)后能否变成数组b。

map的搜索非常高效(这道题很坑,不用map几乎必定TLE)

1.如果d的最后一个不在b里,NO

2.如果b[d]==0,NO

否则YES

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include <bits/stdc++.h>
using namespace std;

int t, n, cache, m;
vector <int> a,diff;
map <int,int> b,d;

void noTLE(){
cin >> n;
for (int i = 0; i < n; i++) {
cin >> cache;
a.push_back(cache);
}
for (int i = 0; i < n; i++) {
cin >> cache;
b[cache]++;
if(a[i] != cache) diff.push_back(cache);
}
cin >> m;
for (int i = 0; i < m; i++) {
cin >> cache;
d[cache]++;
}
if(b[cache]==0){
cout << "NO" <<'\n';
return;
}
for(auto i : diff){
if(d[i]==0){
cout << "NO" <<'\n';
return;
}
d[i]--;
}
cout << "YES" <<'\n';
return;
}

int main(void) {
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
cin >> t;
while (t--) {
noTLE();
diff.clear(); a.clear(); b.clear();d.clear();
}
return 0;
}

D

题目

这道题挺有难度,为了做这题我花了4小时恶补盲点

用欧几里得算法求出相邻数之间的最大公约数并记录到数组b里,然后用sec1和sec2两个子区间来判断切割a[i]后是否满足条件。还要首尾特判(真挺复杂的)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <bits/stdc++.h>
using namespace std;

int t,n,cache,a[200001],b[200001];
int gcd(int a,int b){
return b==0 ? a:gcd(b,a%b);
}
void solve(){
int sec1[200001],sec2[200001];b[n]=99999999;
for(int i=1;i<n;i++) b[i]=gcd(a[i],a[i+1]);
sec1[0]=sec2[n-1]=sec2[n]=1;
for(int i=1;i<n;i++) sec1[i] = sec1[i-1] && b[i-1] <= b[i];
for(int i=n-2;i>0;i--) sec2[i] = sec2[i+1] && b[i] <= b[i+1];
int ans = sec1[n-2] | sec2[2];
for(int i=2;i<n;i++){
int k = gcd(a[i-1],a[i+1]);
ans |= sec1[i-2] && sec2[i+1] && k>=b[i-2] && k<=b[i+1];
}
cout << (ans ? "YES\n" : "NO\n");
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n;
for(int i=1;i<=n;i++){
cin>>cache;
a[i]=cache;
}
solve();
}
return 0;
}

codeforces 871 div4

A

题目

字符串逐个字符比较,签到

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <bits/stdc++.h>
using namespace std;

int t,diff=0;
string cf="codeforces",inp;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> inp;
for(int i=0;i<10;i++){
if(cf[i]!=inp[i]) diff++;
}
cout << diff << '\n';
diff=0;
}
return 0;
}

B

题目

求最长含0区间。本来第一思路是双指针的,结果写的时候发现还有更简单的方法,就按更简单的写了。但是双指针我没怎么练过,所以又写了一份双指针的代码。题不难,耗费的时间很少

两种方法的时间复杂度都是O(n),OJ上显示的用时也都是61ms

代码

easy

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <bits/stdc++.h>
using namespace std;
int t,n,sum=0,sec=0,cache;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n;
for(int i=0;i<n;i++){
cin >> cache;
if(cache==0) {
sec++;
sum=max(sum,sec);
}
else{
sum=max(sum,sec);
sec=0;
}
}
cout << sum << '\n';
sum=sec=0;
}
return 0;
}

two pointers

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include <bits/stdc++.h>
using namespace std;

int t,n,cache,a[101],sum=0;
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n;
for(int i=0;i<n;i++){
cin >> cache;
a[i]=cache+1;
}
if(n==1){
if(a[0]==1){
cout << 1 << '\n';
continue;
}
else{
cout << 0 << '\n';
continue;
}
}
for(int l=0,r=0;l<n && r<n;){
if(a[l]==1 && a[r]==1){
sum = max(sum,r-l+1);
r++;
}
else{
l=r+1;r=l;
}
}
cout << sum <<'\n';
sum=0;
}
return 0;
}

C

题目

输入的时候就处理,m01、m10、m11存放最小值,然后判断比较。这里需要注意m01、m10、m11初始化取的最大值不能为2e5+1,应为4e5+1(因为m01+m10的最值和可能为4e5,我搁这掉坑里了)

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include <bits/stdc++.h>
using namespace std;

int t,n,m01=400001,m10=400001,m11=400001,ca,cm,book;

int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n;
while(n--){
cin >> cm >> book;
if(book == 10) m10 = min(m10,cm);
else if(book == 01) m01 = min(m01,cm);
else if(book == 11) m11 = min(m11,cm);
}
if(m11==400001 && (m01==400001 || m10==400001)) cout << -1 << '\n';
else cout << min(m11,m10+m01) << '\n';
m01=400001,m10=400001,m11=400001;
}
return 0;
}

D

题目

给你一个数n,问你能不能把n拆分后出现数m,拆分的规则是拆成两个数后,一个数是另一个数的两倍。这题DFS搜,有个n==m的特判

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <bits/stdc++.h>
using namespace std;
int t,n,m,cache;
int dfs(int x){
if(x%3 != 0) return 0;
else{
int x1 = x/3, x2 = x-x1;
if(x1==m || x2==m) return 1;
else{
int k =(dfs(x1));
if(!k) k = dfs(x2);
return k;
}
}
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n >> m;
cout << ((dfs(n) || n==m ) ? "YES\n" : "NO\n");
}
return 0;
}

E

题目

二维格子里面,0表示陆地,非零表示湖泊,数字代表湖泊的深度。问相连的湖泊中最深的湖有多深。

BFS搜,用room[][]来判断路是否走过,走过的就不走

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
#include <bits/stdc++.h>
using namespace std;

int room[1002][1002]={0},earth[1002][1002],t,n,m,cache;
int explore[][2]={1,0,-1,0,0,1,0,-1};
struct wei{
int x,y;
};
queue<wei> q;
#define check (next.x>=0 && next.x<n && next.y>=0 && next.y<m && earth[next.x][next.y]!=0 && room[next.x][next.y]==0)

int bfs(int dx,int dy){
wei next,start;
start.x=dx;start.y=dy;int sum=0;
q.push(start);room[dx][dy]=1;
while(!q.empty()){
start = q.front();
q.pop();
sum += earth[start.x][start.y];
for(int i=0;i<4;i++){
next.x=start.x+explore[i][0];next.y=start.y+explore[i][1];
if(check){
room[next.x][next.y]=1;
q.push(next);
}
}
}
return sum;
}
int main(void){
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin >> t;
while(t--){
cin >> n >> m;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
cin >> cache;
earth[i][j]=cache;
room[i][j]=0;
}
}
int sum=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++)
if(earth[i][j] && room[i][j]==0)
sum=max(sum,bfs(i,j));
cout << sum << '\n';
}
return 0;
}