1878(900div3)
A . How Much Does Daytona Cost?
我们将一个整数定义为子段中最常见的整数,如果它在该子段中出现的次数大于该子段中任何其他整数出现的次数。数组的子数段是数组
给定一个大小为
int a[110], num[110];
void solve()
{
memset(a, 0, sizeof a);
memset(num, 0, sizeof num);
int n, m;
cin >> n >> m;
for (int i = 1; i <= n; i++)
cin >> a[i], num[a[i]]++;
if (num[m])
cout << "yes\n";
else
cout << "no\n";
}
B. Aleksa and Stack
给出
Solution
方法很多。
当
int n;
void solve()
{
cin >> n;
int i = 5;
while (n--)
cout << i++ << " ";
cout << '\n';
}
C. Vasilije in Cacak
给出
Solution
只需算出 long long
- 最小:
- 最大:
long long n, k, x, cnt1, cnt2;
void solve()
{
cin >> n >> k >> x;
cnt1 = (k * (k + 1)) / 2;
cnt2 = (k * (2 * n - k + 1)) / 2;
if (x >= cnt1 && x <= cnt2)
cout << "yes\n";
else
cout << "no\n";
}
D. Reverse Madness
给你一个长度为
保证这两个数组满足以下条件:
现在给你一个正整数
每个修改都用一个正整数
, ( )。 。
完成最后一次修改后,输出
对于每个用例:
Solution
做法有:线段树,珂朵莉树, 平衡树,等等很多做法
暴力做法肯定
for (int i = 1; i <= q; i++){
int x;
cin >> x;
for (int j = 1; j <= k; j++){
if (x >= l[j] && x <= r[j]){
int aa = min(x, r[j] + l[j] - x), bb = max(x,r[j] + l[j] - x);
reverse(a.begin() + aa - 1, a.begin() + bb);
break;
}
}
}
Jiangly 做法:
0
(因为偶数的话,就相当于在某个相同区间翻转了偶数次,即相当于没有翻转),奇数置为 1
(相当于在该区间翻转了 1
次)
然后再遍历每一次的 for (int j = l[i]; j <= l[i] + r[i] - j;j++)
相当于是每次只遍历前面一半即
for (int j = l[i]; j <= (l[i] + r[i])/2; j++)

在以 (l+r)/2
为对称轴两侧,如果
Question: 如何证明 swap
的正确性?
void solve()
{
int n, k, q;
cin >> n >>k;
string s;
cin >> s;
vector<int> l(k), r(k), f(n);
for (int i = 0; i < k;i++)
cin >> l[i], l[i]--;
for (int i = 0; i < k;i++)
cin >> r[i], r[i]--;
cin >> q;
while(q--)
{
int x;
cin >> x;
f[x - 1] ^= 1;
}
for (int i = 0; i < k;i++)
{
int rev = 0;
for (int j = l[i]; j <= l[i] + r[i] - j;j++)//for (int j = l[i]; j <= (l[i] + r[i])/2; j++)
{
rev ^= f[j] ^ f[l[i] + r[i] - j];
if(rev)
swap(s[j], s[l[i] + r[i] - j]);
}
}
cout << s << '\n';
}
E . Iva & Pav
定义
给出
输出这样的 -1
Solution
关键在于如何处理 &
,没有看懂题解...
需要用到 ST 表或线段树(学了再说(待更
官方题解:(前缀和加二分)
pref(i, j) 代表整数 i 的二进制表示中在位置 j 的比特位的前缀和
int a[200010], pre[200010][30];
void solve()
{
int n;
cin >> n;
for (int i = 0; i < n; i++)
cin >> a[i];
for (int i = 0; i < n; i++)
{
for (int j = 0; j < 30; j++)
{
if (a[i] & (1 << j))
pre[i + 1][j] = pre[i][j] + 1;
else
pre[i + 1][j] = pre[i][j];
}
}
int q;
cin >> q;
while (q--)
{
int l, k;
cin >> l >> k;
if (a[l - 1] < k)
{
cout << "-1 ";
continue;
}
int low = l, high = n, ans = l;
while (low <= high)
{
int mid = (low + high) / 2, num = 0;
for (int j = 0; j < 30; j++)
if (pre[mid][j] - pre[l - 1][j] == mid - l + 1)
num += (1 << j);
if (num >= k)
low = mid + 1, ans = max(ans, mid);
else
high = mid - 1;
}
cout << ans << ' ';
}
cout << '\n';
}
Jiangly:(没看懂
nxt[i][j]
表示从位置
然后,对于每个查询用例,我们找到最大的索引
最后,如果答案的索引
void solve() {
int n;
std::cin >> n;
std::vector<int> a(n);
for (int i = 0; i < n; i++) {
std::cin >> a[i];
}
std::vector nxt(n + 1, std::vector<int>(30, n));
for (int i = n - 1; i >= 0; i--) {
nxt[i] = nxt[i + 1];
for (int j = 0; j < 30; j++) {
if (~a[i] >> j & 1) {
nxt[i][j] = i;
}
}
}
int q;
std::cin >> q;
while (q--) {
int l, k;
std::cin >> l >> k;
l--;
int ans = l,res = n;
for (int i = 29; i >= 0; i--) {
if (k >> i & 1) {
res = std::min(res, nxt[l][i]);
} else {
ans = std::max(ans, min(res, nxt[l][i]));
}
}
ans = std::max(ans, res);
if (ans <= l) {
ans = -1;
}
std::cout << ans << " ";
}
}
F. Vasilije Loves Number Theory
设
1 x
:将设置为 ,然后回答 是否存在一个正整数 使得 2
:将设置为初始值
Solution
如果
则题目中的
如果
设
利用线性筛法求解积性函数
p[1] = d[1] = ans[1] = 1;//积性函数的定义:f[1]=1
for (int i = 2; i <= n; i ++) {
if (!p[i]) p[i] = i, pr[++ cnt] = i, d[i] = 2, a[i] = 1;
for (int j = 1; j <= cnt && pr[j] * i <= n; j ++) {
p[i * pr[j]] = pr[j];
if (p[i] == pr[j]) {
d[i * pr[j]] = d[i] / (a[i] + 1) * (a[i] + 2);
a[i * pr[j]] = a[i] + 1;
break;
}
else {
d[i * pr[j]] = d[i] * d[pr[j]];
a[i * pr[j]] = 1;
}
}
}
Eg:abc172_d
首先,预先计算每个小于
现在我们需要处理查询:
对于第一个查询,我们在
我们将之前所有类型
时间复杂度
关键是如何处理(没有看懂)
std::vector<int> minp, primes;
constexpr int V = 1E6;
int cnt[V + 1];
void sieve(int n) {//预处理,n=1e6
minp.assign(n + 1, 0);
primes.clear();
for (int i = 2; i <= n; i++) {
if (minp[i] == 0) {
minp[i] = i;
primes.push_back(i);
}
for (auto p : primes) {
if (i * p > n) {
break;
}
minp[i * p] = p;
if (p == minp[i]) {
break;
}
}
}
}
void solve() {
int n, q;
std::cin >> n >> q;
std::vector<int> s;
int d = 1;
auto add = [&](int x, int t = 1) {
while (x > 1) {
int p = minp[x];
x /= p;
d /= cnt[p] + 1;
cnt[p] += t;
d *= cnt[p] + 1;
}
};
s.push_back(n);
add(n);
while (q--) {
int o;
std::cin >> o;
if (o == 1) {
int x;
std::cin >> x;
s.push_back(x);
add(x);
int v = 1;
for (auto x : s) {
v = 1LL * v * x % d;
}
if (v == 0) {
std::cout << "YES\n";
} else {
std::cout << "NO\n";
}
} else {
while (s.size() > 1) {
add(s.back(), -1);
s.pop_back();
}
}
}
while (s.size() > 0) {
add(s.back(), -1);
s.pop_back();
}
std::cout << "\n";
}
G. wxhtzdy ORO Tree
(待更...)