T1
题目有2个人互相操作一个字符串s,第一个人希望把字符串s变得字典序最小,第二个人希望把字符串s变得字典序最大。必须保证每个位置都和之前起始的字符不同,第一个人操作
s
0
s_0
s0,第二个人操作
s
1
s_1
s1,第一个人操作
s
2
s_2
s2依次下去,输出他们会把字符串变成什么样子。
∣
s
∣
≤
50
|s|\leq50
∣s∣≤50
从头遍历字符串,分奇偶判断是谁操作,再判断一下是不是起始就是a或者z。
#include <bits/stdc++.h>
using namespace std;
#define js ios::sync_with_stdio(false);cin.tie(0); cout.tie(0)
#define all(__vv__) (__vv__).begin(), (__vv__).end()
#define endl "\n"
#define pai pair<int, int>
#define ms(__x__,__val__) memset(__x__, __val__, sizeof(__x__))
#define rep(i, sta, en) for(int i=sta; i<=en; ++i)
#define repp(i, sta, en) for(int i=sta; i>=en; --i)
typedef long long ll; typedef unsigned long long ull; typedef long double ld;
inline ll read() { ll s = 0, w = 1; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) if (ch == '-') w = -1; for (; isdigit(ch); ch = getchar()) s = (s << 1) + (s << 3) + (ch ^ 48); return s * w; }
inline void print(ll x, int op = 10) { if (!x) { putchar('0'); if (op) putchar(op); return; } char F[40]; ll tmp = x > 0 ? x : -x; if (x < 0)putchar('-'); int cnt = 0; while (tmp > 0) { F[cnt++] = tmp % 10 + '0'; tmp /= 10; } while (cnt > 0)putchar(F[--cnt]); if (op) putchar(op); }
inline ll gcd(ll x, ll y) { return y ? gcd(y, x % y) : x; }
ll qpow(ll a, ll b) { ll ans = 1; while (b) { if (b & 1) ans *= a; b >>= 1; a *= a; } return ans; } ll qpow(ll a, ll b, ll mod) { ll ans = 1; while (b) { if (b & 1)(ans *= a) %= mod; b >>= 1; (a *= a) %= mod; }return ans % mod; }
const int dir[][2] = { {0,1},{1,0},{0,-1},{-1,0},{1,1},{1,-1},{-1,1},{-1,-1} };
const int MOD = 1e9 + 7;
const int INF = 0x3f3f3f3f;
const int N = 1e6 + 7;
ll n, m;
char s[N];
void solve() {
scanf("%s", s + 1);
n = strlen(s + 1);
rep(i, 1, n) {
if (i & 1) {
if (s[i] == 'a') putchar('b');
else putchar('a');
}
else {
if (s[i] == 'z') putchar('y');
else putchar('z');
}
}
puts("");
}
int main() {
int T = read(); while (T--)
solve();
return 0;
}
T2
给出勇士的攻击力以及血量,后面给出n只怪物,每只怪物也有攻击力与血量。怪物和勇士都是在血量变成0或者负值时就会被杀死,判断勇士是否可以消灭全部的怪物。
n
≤
1
0
5
n\leq10^5
n≤105
我们发现我们只需要判断能不能消灭全部怪物,并不需要找到最大消灭几只怪物,也就是我们要把单回合对勇士造成伤害最高的怪留在最后打一定是最优解。也就是攻击力最高的怪。其他时间计算一下消灭怪物需要几个回合,还要判断一下能不能打完这k个回合。如果消灭一只怪物要打8回合,但是你打到第7回合就没血了的话,肯定无法继续的。这个题目主要就是要按照回合来思考问题,不能把消灭怪物要打k个回合看成一个回合。
const int N = 1e5 + 7;
ll n, m;
pai a[N], my;
void solve() {
my.first = read(), my.second = read();
n = read();
rep(i, 1, n) a[i].first = read();
rep(i, 1, n) a[i].second = read();
sort(a + 1, a + 1 + n);
rep(i, 1, n) {
if (my.second <= 0) { // 勇士已经没血了,但是还剩下了怪
puts("NO");
return;
}
int k = ceil(1.0 * a[i].second / my.first); // 计算消灭这只怪要几回合
if ((k - 1) * a[i].first >= my.second) { // 看下能不能打满k-1回合
puts("NO");
return;
}
my.second -= k * a[i].first;
}
puts("YES");
}
T3
交互题,给出一个长度为n的全排列,但是你并不知道全排列数组长什么样子,只知道长度。你可以进行最多100次查询下标,每查一次下标你就会知道当前下标的对应值,现在要你找到一个位置它的值比左右都要小。
n
≤
1
0
5
n\leq10^5
n≤105
二分查找,假设n ≥ 2 \geq2 ≥2,对于区间[l,r]来说,中点mid的值以及mid+1的值直接查询出来。如果 a [ m i d ] > a [ m i d + 1 ] a[mid]>a[mid+1] a[mid]>a[mid+1],说明mid+1可能是成为答案的那个点,否则如果 a [ m i d ] < a [ m i d + 1 ] a[mid]<a[mid+1] a[mid]<a[mid+1],说明mid是可能成为答案的点,我们依次记录,使用二分维护区间即可。注意把 a [ n + 1 ] a[n+1] a[n+1]赋值为无穷。这样我们最多进行 2 ∗ ⌊ l o g 2 n ⌋ ≤ 50 ≤ 100 2*\lfloor log_2n\rfloor\leq50\leq100 2∗⌊log2n⌋≤50≤100。满足题目意思。
const int N = 1e6 + 7;
ll n, m;
ll a[N];
int query(int x) {
if (1 <= x and x <= n) {
printf("? %d\n", x);
fflush(stdout);
a[x] = read();
}
}
void solve() {
n = read();
if (n == 1) {
puts("! 1");
fflush(stdout);
return;
}
a[0] = a[n + 1] = INF;
int l = 1, r = n, ans = -1;
while (l <= r) {
int mid = l + r >> 1;
query(mid); query(mid + 1);
if (a[mid] < a[mid + 1])
ans = mid, r = mid - 1;
else
l = mid + 1;
}
printf("! %d", ans);
fflush(stdout);
}
T4
给出长度为n的数组,你需要把它按照输入顺序放入两个容器中,并且最终计算单个容器的size需要把连续的一段相同的数看成一个数,计算两个容器的size之和最大是多少。
n
≤
1
0
5
,
p
i
≤
n
n\leq10^5,p_i\leq n
n≤105,pi≤n
我们就模拟这两个容器就行了,发现我们需要知道这个容器最后面放入的元素是什么,可以使用vector的back()成员函数,快速 O ( 1 ) O(1) O(1)拿到。从头到尾遍历数组,那么我们放入的逻辑就是。
- 如果容器a为空我们就把p[i]放入容器a中
- 如果容器a不为空,并且如果p[i+1]==a.back(),说明我们一定要把p[i]放在a容器才会更优。不能把它放在b容器里面去,如果把p[i]放在b里面,之后p[i+1]就不能接在a后面了,可能少一个贡献。对应一组hack样例是n=6 (1 1 2 3 1 1)
- 判断完了前面3个条件,如果容器b为空把p[i]放入容器b
- 同理如果p[i+1]==b.back(),就把p[i]放在b容器,无论p[i]是不是等于b.back()
- 接下来就直接判断一下p[i]会不会和a.back()相等,如果不等就把他放在a容器。
- 否则就丢进b容器里面去。
这题主要的关键点就在判断p[i+1]和容器结尾的关系,比赛的时候一直没想到,只贪心的判断了p[i]和容器的关系,一直wa的第八组样例,枯了。
const int N = 1e6 + 7;
ll n, m;
int p[N];
void solve() {
n = read();
vector<int> a, b;
int ans = 0;
rep(i, 1, n) p[i] = read();
rep(i, 1, n) {
if (a.empty()) a.push_back(p[i]);
else if (a.back() != p[i] and a.back() == p[i + 1]) a.push_back(p[i]);
else if (b.empty()) b.push_back(p[i]);
else if (b.back() != p[i] and b.back() == p[i + 1]) b.push_back(p[i]);
else if (a.back() != p[i]) a.push_back(p[i]);
else b.push_back(p[i]);
}
for (int i = 1; i < a.size(); ++i) {
if (a[i] != a[i - 1]) ++ans;
}
if (a.size()) ++ans;
for (int i = 1; i < b.size(); ++i) {
if (b[i] != b[i - 1]) ++ans;
}
if (b.size()) ++ans;
print(ans);
}