Atcoder ABC399游记(A~D)
66 这回D和上回不同,不是余数性质了
A. Odd Position Sum
题目描述
给你一个整数序列,对于所有i i i 满足1 ≤ 2 ∗ i + 1 ≤ N 1 \leq 2*i+1 \leq N 1 ≤ 2 ∗ i + 1 ≤ N ,计算A i A_i A i 的和。
思路
水
代码
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 main () { int n; cin >> n; vector<int > a (n) ; for (int i = 0 ; i < n; i++) { cin >> a[i]; } int ans = 0 ; for (int i = 0 ; i < n; i++) { if (i % 2 == 0 ) { ans += a[i]; } } cout << ans; return 0 ; }
B.Four Hidden
题目描述
给你一个字符串T T T ,由小写英文字母和?
组成,以及由小写英文字母组成的字符串U U U 。
字符串T T T 是通过取一个仅小写的字符串S S S ,并用?
恰好替换其中的四个字符来获得的。
告诉我S S S 是否可能包含U U U 作为连续子字符串。
思路
水 等等怎么挂了两发
杂乱的代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 #include <bits/stdc++.h> using namespace std;int main () { string s, t; cin >> s >> t; for (int i = 0 ; i + t.length () - 1 < s.length (); i++) { bool check = 1 ; for (int j = 0 ; j < t.length (); j++) { if (s[i + j] != t[j] && s[i + j] != '?' ) { check = 0 ; break ; } } if (check == 1 ) { cout << "Yes" ; return 0 ; } } cout << "No" ; return 0 ; }
C.403 Forbidden
问题陈述
某软件上上有 N N N 个用户,编号从 1 1 1 到 N N N ,还有 M M M 个页面,编号从 1 1 1 到 M M M 。最初,没有用户有查看任何竞赛页面的权限。
按顺序处理 Q Q Q 查询。每个查询都是以下三种类型之一:
一个用户可能多次被授予同一页面的权限。
思路
map实现即可,最多多个是否是超级用户数组,水啊
有用bit做的????????????????????
代码
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 #include <bits/stdc++.h> using namespace std;map<pair<int , int >, bool > mp; bool vis[222222 ];int main () { int n, m; cin >> n >> m; int T; cin >> T; while (T--) { int ch; cin >> ch; if (ch == 1 ) { int x, y; cin >> x >> y; mp[{x, y}] = 1 ; } else if (ch == 2 ) { int x; cin >> x; vis[x] = 1 ; } else { int x, y; cin >> x >> y; cout << (vis[x] || mp[{x, y}] ? "Yes" : "No" ) << '\n' ; } } return 0 ; }
D.Forbidden Difference
题目描述
给你一个长度为N N N 的数组A A A 和一个D D D ,问你最少删除多少个元素,可以满足:
对于任意1 ≤ i , j ≤ N 1 \leq i,j \leq N 1 ≤ i , j ≤ N ,满足∣ A i − A j ∣ ≠ D |A_i - A_j| \not= D ∣ A i − A j ∣ = D
思路
这个D D D 最大到1e6。。。。
赛时想到其实可以取模D D D 的完全剩余系,对于每个数都可以构成一条链,然后对这条链动态规划就行了!!!
具体怎么动态规划呢,我们首先设M M M 为A A A 中有多少种数模D D D 的余数为当前的r r r 。
然后d p i dp_i d p i 就表示我们对于前i i i 种可以最多不删的数的个数,所以要么选i − 2 i-2 i − 2 加上当前数字个数,要么选i − 1 i-1 i − 1 ,因为根据题目的定义,留下来的不能相邻。
所以就简单了,但是还要特判D为0的情况!
不知道atc出多少次D题DP了
代码
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 #include <bits/stdc++.h> using namespace std;#define int long long signed main () { int n, d; cin >> n >> d; vector<int > a (n) ; for (int i = 0 ; i < n; i++) { cin >> a[i]; } int maxx = -1 ; for (int i = 0 ; i < n; i++) { maxx = max (maxx, a[i]); } vector<int > cnt (maxx + 1 , 0 ) ; for (int i = 0 ; i < n; i++) { cnt[a[i]]++; } if (d == 0 ) { int ans = 0 ; for (int i = 0 ; i < cnt.size (); i++) { if (cnt[i] > 0 ) { ans++; } } cout << (n - ans); return 0 ; } int ans = 0 ; for (int r = 0 ; r < d; r++) { vector<int > lian; for (int x = r; x <= maxx; x += d) { lian.push_back (cnt[x]); } int m = lian.size (); if (m == 0 ) { continue ; } vector<int > dp (m, 0 ) ; dp[0 ] = lian[0 ]; if (m > 1 ) { dp[1 ] = max (lian[0 ], lian[1 ]); } for (int i = 2 ; i < m; i++) { dp[i] = max (dp[i - 1 ], dp[i - 2 ] + lian[i]); } ans += dp[m - 1 ]; } cout << (n - ans); return 0 ; }