10-14

A

A-尖子生

分成jzc、jz、zc、d四种情况即可

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 <iostream>
#include <cstring>
using namespace std;
int main()
{
string s;
cin >> s;
int c1 = 0, c2 = 0, c3 = 0;
for(int i = 0; i < s.size(); i++)
{
if(s[i] == 'j')
{
if(s[i + 1] == 'z')
{
if(s[i + 2] == 'c')//如果是jzc
{
c1++, c2++;
i += 2;
}
else
{
c1++;
i += 1;
}
}
else
{
continue;
}
}
else if(s[i] == 'z')
{
if(s[i + 1] == 'c')
{
c2++;
i += 1;
}
else
continue;
}
else if(s[i] == 'd')
{
c3++;
}
}
cout << c1 << " " << c2 << " " << c3 ;
return 0;
}

B

B-建房子

考察离散化,用结构体存下搭建的起点和终点,起点标记为1,终点标记为-1,通过加上起点或终点的标记判断当前的高度,为保证正确性,起点应该排在终点的前面。如果当前高度大于已经记录的高度,就更新高度和最高的个数;如果当前高度等于最高高度,就加上最高高度

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
#include <iostream>
#include <algorithm>
using namespace std;
#define int long long
const int N = 1e6 + 10;
struct re
{
int x, f;
}a[N * 2];//x用来记录输入的l,r;f用来记录是起点还是终点
bool cmp(re a, re b)
{
if(a.x == b.x) return a.f > b.f;
return a.x < b.x;
}
signed main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i * 2 - 1].x, a[i * 2 - 1].f = 1;//起点
cin >> a[i * 2].x, a[i * 2].f = -1;//终点
}
int nh = 0;//nh用来记录当前的高度
int mc = 0, mh = 0;//mc用来记录最大个数,mh最大高度
for(int i = 1; i <= 2 * n; i++)
{
nh += a[i].f;
if(nh > mh)
{
mh = nh;
mc = a[i + 1].x - a[i].x + 1;//直接更新
}
else if(nh == mh)
{
mc += a[i + 1].x - a[i].x + 1;//在过去的基础上加
}
}
cout << mh << " " << mc;
return 0;
}

C

C-连通图

分成环、不成环;o可以1:2连接,也2:2连接

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 <iostream>
using namespace std;
#define int long long
void solve()
{
int c, o, h;
cin >> c >> o >> h;
if(h % 2 == 1 || h > 2 * c + 2)//如果h是奇数,或者比最大分支多
{
cout << "NO" << '\n';
return;
}
if(c == 0)//如果没有c
{
if(h == 2) cout << "YES" << '\n';
else if(o > 2 && h == 0) cout << "YES" << '\n';
else cout << "NO" << '\n';
}
else if(c == 1)//只有一个c,o不能1:2
{
if(o >= 2 * c + 2 - h) cout << "YES" << '\n';
else cout << "NO" << '\n';
}
else if(c == 2)//有两个c,c不能成环,但是o可以1:2
{
if(o >= (2 * c + 2 - h) / 2) cout << "YES" << '\n';
else cout << "NO" << '\n';
}
else//c可以成环的情况
{
if(o >= (2 * c + 2 - h) / 2) cout << "YES" << '\n';
else if(h <= 2 * c)
{
if(o >= (2 * c - h) / 2) cout << "YES" << '\n';
else cout << "NO" << '\n';
}
else cout << "NO" << '\n';
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
int t;
cin >> t;
while(t--)
{
solve();
}
return 0;
}

10-16

A

A-Happy! 美咲的翻翻乐

模拟即可

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;
const int N = 1e5 + 10;
int a[N];
int ans = 0;
int main()
{
int n;
cin >> n;
int c = 0;
n = 2 * n;
while(n--)
{
int x;
cin >> x;
if(!a[x])
{
a[x] = 1;
c++;
ans = max(ans, c);
}
else
c--;
}
cout << ans;
return 0;
}

B

B-Lucky! 米歇尔的加法

先将两个数补齐,转换成十进制,然后这个“加法”相当于异或,再转换成十六进制,删除前导零即可。注意如果是全零时的特判

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 <iostream>
#include <vector>
using namespace std;
vector<char> a;
int main()
{
string x0, y;
cin >> x0 >> y;
string x = "";
if (x0.size() > y.size()) swap(x0, y);//让x0是短的字符串
for (int i = y.size() - x0.size(); i > 0; i--)
{
x += '0';
}
x += x0;
for (int i = 0; i < x.size(); i++)
{
//将xy的每一位转换成十进制
int x10, y10;
if (x[i] >= 'A' && x[i] <= 'Z')
x10 = x[i] - 'A' + 10;
else
x10 = x[i] - '0';
if (y[i] >= 'A' && y[i] <= 'Z')
y10 = y[i] - 'A' + 10;
else
y10 = y[i] - '0';

int ians = x10 ^ y10;
char cans;
//转换成十六进制
if (ians >= 0 && ians <= 9) cans = ians + '0';
if (ians >= 10 && ians <= 15) cans = ians - 10 + 'A';
a.push_back(cans);
}
int i = 0;
while (i < a.size() && a[i] == '0') i++;//删除前导零
if (i == a.size()) cout << 0;//0的特判
for (; i < a.size(); i++)
cout << a[i];
return 0;
}

C

C-Smile! 花音的礼物分配

利用背包问题,列举所有可能的情况

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
#include <bits/stdc++.h>
using namespace std;
vector<int> ac;
const int N = 510;
int sum1 = 0, sum2 = 0, s = 0, f[N * N];
int main()
{
int n;
cin >> n;
while(n --)
{
int a, b;
cin >> a >> b;
if(b == 0) ac.push_back(a), s += a;//可自由支配
else if(b == 1) sum1 += a;
else sum2 += a;
}
int ans = s + sum1 + sum2;//最差的情况
f[sum1] = 1;//sum1可达
for(int i = 0; i < ac.size(); i++)
{
for(int j = sum1 + s; j >= ac[i]; j--)
{
f[j] |= f[j - ac[i]];
}
}

for(int i = 0; i <= s + sum1; i++)
{
if(f[i])
{
ans = min(ans, abs(s + sum1 + sum2 - 2 * i));
}
}
cout << ans;
return 0;
}

D

D-Yeah!! 弦卷心的好子串

双指针法,记录h、hw、w的个数

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
#include <bits/stdc++.h>
#define int long long
using namespace std;
int n, k;
string x, a = "";
int h, w, hw, s, ans;
signed main()
{
cin >> n >> k;
cin >> x;
for(int i = 0; i < n; i++)
if(x[i] == 'h' || x[i] == 'w') a += x[i];//a是只有h和w的字符串
int m = a.size();
for(int i = 0, j = -1; i < m; i++)
{
//查找符合条件子串的右端点j
while(j < m && s < k)
{
j++;
if(a[j] == 'h') h++;
else//如果是w
{
w++;
hw += h;
s += h * (h - 1) / 2;
}
}
ans += m - j;

if(a[i] == 'h')
{
h--;
hw -= w;
s -= hw;
}
else
w--;
/*cout << '\n';
cout << j << '\n';
cout << ans << '\n';
cout << '\n';*/
}
cout << ans;
return 0;
}