Codeforces Global Round 7
https://codeforces.com/contest/1326
输出n位数,使得这个数字不能被它含有的单个数字整除
特判掉1,直接输出233-- || 277-- 就可以了,比赛的时候**输出了一个 288--,然后整了半天。
#include <bits/stdc++.h> #define ll long long #define sc scanf #define pr printf using namespace std; const int MAXN = 1e5 + 5; ll a[MAXN]; int main() { int T; sc("%d", &T); while (T--) { int n; sc("%d", &n); if (n == 1) pr("-1\n"); else { for (int i = 0; i < n - 1; i++) pr("2"); pr("8\n"); } } }
按照题意反着模拟就行了,不过非常容易出错。
题目的意思是 等于数组 a 的前 i-1 项的最大值(x1=0),然后
给你 b 数组,让你求出 a 数组。
所以首先可以确定 a1=b1, 然后迭代的同时,先更新 xi,再算出 ai 即可,理顺了思路就可以很快做出
#include <bits/stdc++.h> #define ll long long #define sc scanf #define pr printf using namespace std; const int MAXN = 2e5 + 5; ll b[MAXN],a[MAXN],x[MAXN]; int main() { { int n; sc("%d", &n); for (int i = 1; i <= n; i++) sc("%lld", &b[i]); x[1] = 0; a[1] = b[1]; for (int i = 2; i <= n; i++) { x[i] = max(x[i - 1], a[i - 1]); a[i] = x[i] + b[i]; } for (int i = 1; i <= n; i++) pr("%lld%c", a[i], i == n ? '\n' : ' '); } }
将长度为 n 的全排列数组分为 k 段,求每段最大值的和 和 有多少种切分方式使得取到最大值
首先最大值肯定是最大的 k 个数字,考虑将 k 个最大的数字作为 k 段,然后每两端之间的元素就可以随便选,所以累乘一下就可以了。
#include <bits/stdc++.h> #define ll long long #define sc scanf #define pr printf using namespace std; const int MAXN = 2e5 + 5; const ll mod = 998244353; ll a[MAXN], pos[MAXN]; int main() { ll n, k; sc("%lld%lld", &n, &k); ll cnt = 0, ans1 = 0, ans2 = 1; for (int i = 1; i <= n; i++) { sc("%lld", &a[i]); if (a[i] > n - k) { pos[i] = 1; ans1 += a[i]; } } bool f = false; for (int i = 1; i <= n; i++) { if (pos[i] == true) { if (f == true) ans2 = ans2 * (cnt + 1) % mod; cnt = 0; f = true; } else cnt++; } pr("%lld %lld\n", ans1, ans2); }
D1 - Prefix-Suffix Palindrome (Easy version)
D2 - Prefix-Suffix Palindrome (Hard version)
给你一个字符串,可以选择一个前缀和一个后缀(可以为空),求前缀+后缀,形成的串是回文串的最大长度,并输出最长回文串。
前缀+后缀,所以显然我们可以先将两端相等的字母去掉,因为这些一定在答案中,然后将剩下的字符串拿出来,得到剩下的字符串的包含开头或结尾的最长对称子串就可以了,考虑manacher,在求出了每个点作为中心点的对称半径后,判断一下是否是边界,然后更新答案即可。
#include <bits/stdc++.h> #define ll long long #define sc scanf #define pr printf using namespace std; const int MAXN = 5e6 + 5; int r[MAXN]; char s[MAXN]; char a[MAXN]; char aa[MAXN]; void malache(char a[]) { int ans = 0, f = 0; int len = strlen(a); int cnt = 0; s[cnt++] = '%'; s[cnt++] = '*'; for (int i = 0; i < len; i++) { s[cnt++] = a[i]; s[cnt++] = '*'; } s[cnt++] = '^'; r[0] = 0; int maxn = 0; int id = 0; for (int i = 1; i < cnt - 1; i++) { if (i < maxn) r[i] = min(maxn - i, r[2 * id - i]); else r[i] = 1; while (s[i - r[i]] == s[i + r[i]]) r[i]++; if (i + r[i] > maxn) { maxn = i + r[i]; id = i; } if (r[i] > ans && (i + r[i] >= 2 * len + 1 || i - r[i] <= 1)) { ans = r[i]; f = i; } } for (int i = f - ans + 1; i <= f + ans - 1; i++) { if (isalpha(s[i])) pr("%c", s[i]); } } //index 0 2 4 6 8 10 12 // s % a b c b a ^ // r 0 2 2 6 2 2 0 int main() { int T; sc("%d", &T); while (T--) { sc("%s", a); int len = strlen(a), cnt = 0; for (int i = 0; i < len / 2; i++) { if (a[i] == a[len - 1 - i]) cnt = i + 1; else break; } int qq = 0; for (int i = 0; i < cnt; i++) pr("%c", a[i]); for (int i = cnt; i < len - cnt; i++) aa[qq++] = a[i]; aa[qq] = '\0'; malache(aa); for (int i = len - cnt; i < len; i++) pr("%c", a[i]); pr("\n"); } }
如果答案为 k 是不行的,那么所以 >=k 的点是可以被删除的,说明从右往左数 第一个 >=k 的点的右边至少有一个炸弹炸掉这个点,第二个 >=k 的点的右边至少有二个炸弹炸掉这个点和上一个点,第 x 个 >=k 的点的右边至少有 x个炸弹炸掉这 x 个点,由于答案是不增的,所以我们每次判断当前答案是否可行,考虑线段树维护即可。(细节待更新)
#include <bits/stdc++.h> //#define ll long long #define sc scanf #define pr printf #define lson left,mid,k<<1 #define rson mid+1,right,k<<1|1 #define imid int mid = (left + right) >> 1; using namespace std; const int MAXN = 3e5 + 5; struct node { int maxn; int mark; }que[MAXN << 2]; int a[MAXN], n; void up(int k) { que[k].maxn = max(que[k << 1].maxn, que[k << 1 | 1].maxn); } void down(int k) { if (que[k].mark) { que[k << 1].mark += que[k].mark; que[k << 1 | 1].mark += que[k].mark; que[k << 1].maxn += que[k].mark; que[k << 1 | 1].maxn += que[k].mark; que[k].mark = 0; } } void build(int left, int right, int k) { que[k].mark = 0; if (left == right) { que[k].maxn = 0; return; } imid; build(lson); build(rson); up(k); } void update(int left, int right, int k, int ql, int qr, int val) { if (qr < left || right < ql) return; if (ql <= left && right <= qr) { que[k].maxn += val; que[k].mark += val; return; } down(k); imid; update(lson, ql, qr, val); update(rson, ql, qr, val); up(k); } int query(int left, int right, int k, int ql, int qr) { if (qr < left || right < ql) return 0; if (ql <= left && right <= qr) return que[k].maxn; down(k); imid; return max(query(lson, ql, qr), query(rson, ql, qr)); } int q[MAXN]; int pos[MAXN]; int main() { sc("%d", &n); for (int i = 1; i <= n; i++) { sc("%d", &a[i]); pos[a[i]] = i; } for (int i = 1; i <= n; i++) sc("%d", &q[i]); //build(1, n, 1); int ans = n; pr("%d", ans); update(1, n, 1, 1, pos[n], 1); for (int i = 1; i < n; i++) { update(1, n, 1, 1, q[i], -1); while (query(1, n, 1, 1, n) <= 0) { ans--; update(1, n, 1, 1, pos[ans], 1); } pr(" %d", ans); } }