A题 CodeForces - 1234A
Example
Input
3
5
1 2 3 4 5
3
1 2 2cpp
4
1 1 1 1
Output
3
2
1
想复杂了,直接计算平均值向上取整
#include
using namespace std;
const int N = 110;
int a[N], t, n;
int main() {
//freopen("in.txt", "r", stdin);
ios::sync_with_stdio(false), cin.tie(0);
cin >> t; while (t--) {
int sum = 0;
cin >> n;
for (int i = 1; i <= n; ++i)cin >> a[i], sum += a[i];
int p = sum / n * n >= sum ? sum / n : sum / n + 1;
cout << p << endl;
}
}
B题 CodeForces - 1234B2
Examples
Input
7 2
1 2 3 2 1 3 2
Output
2
2 1
Input
10 4
2 3 3 1 1 2 1 2 3 3
Output
3
1 3 2
B题和C题是一样的只需要考虑数据规模即可
C题数据范围 \(1 <= d_i <= 10^9\)
思路:
根据题意,用队列模拟下,set存储目前显示的消息内容
#include
using namespace std;
typedef long long ll;
deque q;
set s;
int main() {
//freopen("in.txt", "r", stdin);
int n, k;
cin >> n >> k;
for (int i = 1, x; i <= n; i++) {
cin >> x;
if (s.find(x) != s.end()) continue;//如果存在就跳过
s.insert(x);
q.push_front(x);
if (q.size() > k) {
s.erase(q.back());
q.pop_back();
}
}
cout << q.size() << '\n';
for (auto x : q)
cout << x << ' ';
}
D题:
CodeForces - 1234C
写的时候考虑不完全,这道题,我们可以把序号1、2的看成是一样的,再把序号3、4、5、6看成是一样的,所以在这里我看成了1号整体与2号整体。
然后,其实我们不难发现,路径是唯一的,也就是说我们的走法是唯一的,我们只需要判断下一步是不是还可以走就可以了。还有到达终点的过程。
AC代码
#include
using namespace std;
const int maxN = 2e5 + 7;
int N, dir[3][maxN];
char op[3][maxN];
inline bool dfs(int x, int y, int las_op, int lx, int ly){
if (x == N + 1 && y == 1) return true;
if (x > N || y > 2 || y < 1) return false;
if (dir[y][x] == 1){
if (lx == x) return false;
return dfs(x + 1, y, 1, x, y);
}
else {
if (lx == x) return dfs(x + 1, y, 2, x, y);
else return dfs(x, 3 - y, 2, x, y);
}
}
int main(){
freopen("in.txt", "r", stdin);
int T; scanf("%d", &T);
while (T--) {
scanf("%d", &N);
for (int i = 2; i >= 1; i--) scanf("%s", op[i] + 1);
for (int i = 1; i <= 2; i++) {
for (int j = 1; j <= N; j++){
if (op[i][j] <= '2') dir[i][j] = 1;
else dir[i][j] = 2;
}
}
bool flag;
if (dir[2][1] == 1) flag = dfs(2, 2, 1, 1, 2);
else flag = dfs(1, 1, 2, 1, 2);
printf(flag ? "YES\n" : "NO\n");
}
return 0;
}
E题:
CodeForces - 1234D
线段树、set容器
最先做的时候使用set容器但没剪枝,直接在大数据TLE,改用26个字母的线段树才过
#include
using namespace std;
const int maxn = 1e5 + 100;
char str[maxn];
struct node {
int l, r, sum;
}tr[26][maxn << 2];
void build(int root, int l, int r) {
for (int i = 0; i < 26; i++) {
tr[i][root].l = l; tr[i][root].r = r; tr[i][root].sum = 0;
}
if (l == r)//重合返回即可
return;
int mid = (l + r) >> 1;
build(root << 1, l, mid);
build(root << 1 | 1, mid + 1, r);
}
void update(int root, int trnum, int pos, int num) {
if (tr[trnum][root].l == tr[trnum][root].r) {
tr[trnum][root].sum += num;
return;
}
int mid = (tr[trnum][root].l + tr[trnum][root].r) >> 1;
if (pos <= mid) {
update(root << 1, trnum, pos, num);
}
else {
update(root << 1 | 1, trnum, pos, num);
}
tr[trnum][root].sum = tr[trnum][root << 1].sum + tr[trnum][root << 1 | 1].sum;
}
int query(int root, int trnum, int L, int R) {
if (tr[trnum][root].l == L && tr[trnum][root].r == R)
return tr[trnum][root].sum;
int mid = (tr[trnum][root].l + tr[trnum][root].r) >> 1;
if (R <= mid)
return query(root << 1, trnum, L, R);
else if (L > mid)
return query(root << 1 | 1, trnum, L, R);
else
return query(root << 1, trnum, L, mid) + query(root << 1 | 1, trnum, mid + 1, R);
}
int main() {
//freopen("in.txt", "r", stdin);
int n, m, opt, x, y;
char ss[5]; str[0] = '#';
scanf("%s", &str[1]);
n = strlen(str) - 1;
build(1, 1, n);
cin >> m;
for (int i = 1; i <= n; i++) {
update(1, str[i] - 'a', i, 1);
}
while (m--) {
cin >> opt;
if (opt == 1) {
cin >> x >> ss;
if (str[x] != ss[0]) {
update(1, str[x] - 'a', x, -1);
update(1, ss[0] - 'a', x, 1);
str[x] = ss[0];
}
}
else {
cin >> x >> y;
int c = 0;
for (int i = 0; i < 26; i++) {
if (query(1, i, x, y)) {
c++;
}
}
printf("%d\n", c);
}
}
}
贴一下dalao的set容器写法,作为学习
思路:这里用到了一个比较巧妙的技巧,用26个set来存储每个字母在字符串中出现的位置,因为STL中set是排序的,所以每次查询时,只需要遍历26个字母,查询其在字符串中第一次出现的在l之后的位置,若该位置比r要小,说明这个字符存在于这个区间之内,答案加1。更新时只需要在原串位置的字符对应的set中去除这个位置,并在新替换的字符对应的set中存入该位置即可。
#include
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 1e5+10;
const int mod = 1e9+7;
const int inf = 0x3f3f3f3f;
char s[maxn];
int q;
set Set[26];
int main()
{
scanf("%s", s+1);
cin >> q;
int n = strlen(s+1);
for (int i = 1; i <= n; i++)
Set[s[i]-'a'].insert(i);
for (int i = 0; i < q; i++) {
int op;
cin >> op;
if (op == 1) {
int p; char c;
scanf("%d %c", &p, &c);
int cur = s[p]-'a';
if (Set[cur].count(p))
Set[cur].erase(Set[cur].find(p));
s[p] = c;
Set[c-'a'].insert(p);
} else {
int l, r, ans = 0;
scanf("%d%d", &l, &r);
for (int j = 0; j < 26; j++) {
int cur = *Set[j].lower_bound(l);
if (cur >= l && cur <= r) {
ans++;
}
}
cout << ans << "\n";
}
}
return 0;
}