CodeTON Round 7 (Div. 1 + Div. 2)

傻逼 一直卡D题卡烂了

CodeTON Round 7 (Div. 1 + Div. 2)

A

由冒泡排序思想,显然只要一轮一轮尽可能进行操作直到数列升序即可,如果没升序就无法进行任何操作了就是NO。

 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;

typedef long long ll;

bool solve() {
	int n, a[15];
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
	}
	while (true) {
		bool sorted = true;
		for (int i = 2; i <= n; ++i) {
			if (a[i - 1] > a[i]) {
				sorted = false;
				break;
			}
		}
		if (sorted) return true;
		bool canop = false;
		for (int i = 2; i <= n - 1; ++i) {
			if (a[i - 1] < a[i] && a[i] > a[i + 1]) {
				canop = true;
				swap(a[i], a[i + 1]);
			}
		}
		if (!canop) return false;
	}
}

int main() {
	// ios::sync_with_stdio(false);
	// cin.tie(nullptr); cout.tie(nullptr);
	int t;
	// cin >> t;
	scanf("%d", &t);
	while (t--) {
		printf(solve() ? "YES\n" : "NO\n");
	}
	return 0;
}

B

考虑AAAABBBB,最好情况是把第一个B挪到所有A左边,把最后一个A挪到所有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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5+3;

bool a[N] = {0};
void solve() {
	int n;
	scanf("%d\n", &n);
	for (int i = 1; i <= n; ++i) {
		a[i] = getchar() == 'A';
	}
	getchar();
	int i, ans = 0, cnt0 = 0;
	for (i = n; i >= 1;) {
		if (!a[i]) {
			++cnt0;
			--i;
			continue;
		}
		for (; a[i]; --i) {
			if (cnt0) ++ans;
		}
		if (cnt0 > 1) ans += cnt0 - 1;
		if (cnt0) cnt0 = 1;
	}
	printf("%d\n", ans);
}

int main() {
	// ios::sync_with_stdio(false);
	// cin.tie(nullptr); cout.tie(nullptr);
	int t;
	// cin >> t;
	scanf("%d\n", &t);
	while (t--) {
		solve();
	}
	return 0;
}

C

贪心,b中最小的x个和a中最大的x个升序配对,剩下的升序配对。

 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
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
const int N = 2e5+3;

int b[N], ans[N];
pair<int, int> a[N];
int solve() {
	int n, x;
	scanf("%d %d", &n, &x);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i].first);
		a[i].second = i;
	}
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &b[i]);
	}
	sort(b + 1, b + n + 1);
	
	for (int i = 1; i <= n - x; ++i) {
		if (a[i].first > b[x + i]) return 0;
		ans[a[i].second] = b[x + i];
	}
	for (int i = n - x + 1, j = 1; i <= n; ++i, ++j) {
		if (a[i].first <= b[j]) return 0;
		ans[a[i].second] = b[j];
	}
	printf("YES\n");
	for (int i = 1; i <= n; ++i) {
		printf("%d ", ans[i]);
	}
	printf("\n");
	return 1;
}

int main() {
	// ios::sync_with_stdio(false);
	// cin.tie(nullptr); cout.tie(nullptr);
	int t;
	// cin >> t;
	scanf("%d", &t);
	while (t--) {
		if (!solve()) {
			printf("NO\n");
		}
	}
	return 0;
}

D

可用在树状数组上二分的方法求得序列的一个前缀,使得其和刚好>=s。记这个前缀的和为x。若x=s则YES,若s!=x只有一种可能性,即x=s+1且前缀的最后一个数是2。此时考虑向右移动左端点。

  • 若左端点处为1,将左端点向右移动1即可YES
  • 若左端点为2,右端点右边一个为1,则将左右端点向右都移动1即可YES
  • 若左端点为2,右端点右边一个为2,则将左右端点向右都移动1,重复进行前面的判断。

于是,右端点右边只要存在1就可以YES,左端点右边存在1且将左端点移到这里不会导致右端点超出n就可以YES,其余情况NO。

  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
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
#include <bits/stdc++.h>
using namespace std;

typedef long long ll;

template<class T> struct BIT {
	int n;
	T *t;
	bool need_free = true;

	inline int lb(int x) {
		return x & (-x);
	}

	// 构造空树状数组
	BIT(int n) {
		this->n = n;
		t = new T[n + 1]();
	}

	// n:数据数量 a:数据源(下标1开始) inplace:利用传入的数组
	BIT(int n, T *a, bool inplace = false) {
		this->n = n;
		need_free = !inplace;
		t = inplace ? a : new T[n + 1]();
		for (int i = 1; i <= n; ++i) {
			if (!inplace) t[i] = a[i];
			for (int x = lb(i) >> 1; x; x >>= 1) {
				t[i] += t[i - x];
			}
		}
	}

	~BIT() {
		if (need_free) delete[] t;
	}

	// 单点修改 a[x] += k
	void add(int x, T k) {
		for (; x <= n; x += lb(x)) t[x] += k;
	}

	// 查询前缀和
	T prefix(int x) {
		T c = 0;
		for (; x; x -= lb(x)) c += t[x];
		return c;
	}

	// 查询区间和
	T sum(int x, int y) {
		return prefix(y) - prefix(x - 1);
	}
};

const int N = 1e5+5;
int a[N];

void solve() {
	int n, q;
	scanf("%d %d", &n, &q);
	set<int> one;
	for (int i = 1; i <= n; ++i) {
		scanf("%d", &a[i]);
		if (a[i] == 1) {
			one.insert(i);
		}
	}
	BIT<int> pre(n, a, false);
	int op, s, i, v;

	auto fnd = [&](int x) -> int {
		int l = 1, r = n;
		while (l < r - 3) {
			int m = (l + r) / 2;
			if (pre.prefix(m) >= x) r = m;
			else l = m + 1;
		}
		for (int i = l; i <= r; ++i) {
			if (pre.prefix(i) >= x) return i;
		}
		return -1;
	};

	while (q--) {
		scanf("%d", &op);
		if (op == 1) {
			scanf("%d", &s);
			i = fnd(s);
			if (i == -1) {
				printf("NO\n");
				continue;
			}
			if (pre.prefix(i) == s || one.upper_bound(i) != one.end()) {
				printf("YES\n");
				continue;
			}
			if (one.size() == 0) {
				printf("NO\n");
				continue;
			}
			int t = *one.begin();
			if (t + i - 1 <= n) {
				printf("YES\n");
				continue;
			}
			printf("NO\n");
		} else {
			scanf("%d %d", &i, &v);
			if (a[i] == v) continue;
			a[i] = v;
			if (v == 1) {
				one.insert(i);
				pre.add(i, -1);
			} else {
				one.erase(i);
				pre.add(i, 1);
			}
		}
	}
}

int main() {
	// ios::sync_with_stdio(false);
	// cin.tie(nullptr); cout.tie(nullptr);
	int t;
	// cin >> t;
	scanf("%d", &t);
	while (t--) {
		solve();
	}
	return 0;
}
Licensed under CC BY-NC-SA 4.0
无网ICP备 1145141919810
Built with Hugo
主题 StackJimmy 设计