Codeforces Global Round 23 F. Kazaee
题目大意:
给一个数组,然后有单点修改操作,还有求一个区间内所有数字出现的次数都是k的倍数的操作,如果区间所有数字都是k的倍数,那么输出YES否则输出NO。
大致思路:
我们会发现无论用什么数据结构去维护似乎都不太可行,这题好像所有人都是用的一个方法:用一个极极极极极极极极大概率正确的算法,但是不能称之为完全正确的算法。
因为数据范围到了1e9,所以我们先将所有的数值进行离散化。对于每个数值,如果他出现的次数是k的倍数,那么他和其他出现次数也是k的倍数的数的数量加起来也还是k的倍数。我们考虑把区间所有数字出现次数加起来。那么如果一个数出现的次数是k的倍数那么我们不统计他是不是也不影响答案?。那么反过来如果一个不是k的倍数,那么他一旦不被统计的话整体的和是不是就不是k的倍数了。
就设k为2,我们选择了[1,1,1,3,3,3,4,4,5,5]这么一个区间,如果只不统计1出现的次数而其他全部统计的话那么是不是等于7,就不是2的倍数了。如果只不统计3出现的次数也是同理。只不统计4出现的次数的话是不会影响是否为区间每个数字出现的次数是否为k的倍数,5也同理。那么我们考虑随机化统不统计哪些数值。我们开一个used数组,对于每一个离散化后的范围,我们used数组进行随机初始化,随机完之后他为1,那么说明这个数值需要纳入数量统计,如果为0,则不纳入答案统计。我们将1,3,4,5离散化之后分别对应0,1,2,3。那么如果used[0] = 1,used[1] = 0,或者used[0] = 0, used[1] = 1,出现了任意一种情况的话这个区间所有需要被统计的数量加起来就不是k的倍数了,出错的概率是1/2。那么我们开30个used数组,每个都进行随机,然后判断每个数组,有一个不合法就输出NO。那么出错的概率是不是1/2的30次方,那么这个算法可以近似认为是完全正确的算法。
当然k为2其实是最坏情况了。当k为除了1和2以外的任意其他数字,这个出错的概率都会越来越低。我们可以假设k为13,那么如果区间里面有5种不同的数字,出现的次数分别为26, 1, 2, 5, 5的话。除非我们后面四种数字全部在每个used里面全部被置为1或者被置为0,那么这个概率已经比k等于2低了。
因为jiangly的板子我不会开一维数组,但是刚刚说完队友的板子是lj,并且吹捧jiangly的最棒,硬着头皮写完了30个树状数组的模拟。
贴一发zjn已经AC的代码吧。我代码观赏性极差,但是节目效果拉满。还是建议看zjn代码。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 600010;
struct fenwickTree {
ll tr[N];
int lowBit(int x) {return x & -x;}
void upd(int x, ll v) {for (int i = x; i <= N - 10; i += lowBit(i)) tr[i] += v;}
ll query(int x) {
ll res = 0;
for (int i = x; i; i -= lowBit(i)) res += tr[i];
return res;
}
};
fenwickTree f[31];
int n, m, cnt, a[N], valid[31][N];
map<int, int> idx;
int get(int x) {
if (!idx.count(x)) idx[x] = ++cnt;
return idx[x];
}
int main() {
random_device rd;
default_random_engine eng(rd());
uniform_int_distribution<int> distr(0, 1);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
a[i] = get(a[i]);
}
for (int i = 1; i <= 30; i++) {
for (int j = 1; j <= N - 10; j++) {
valid[i][j] = distr(eng);
}
for (int j = 1; j <= n; j++) {
if (valid[i][a[j]]) {
f[i].upd(j, 1);
}
}
}
for (int i = 1, mod; i <= m; i++) {
scanf("%d", &mod);
if (mod == 1) {
int pos, v;
scanf("%d%d", &pos, &v);
int idx = get(v);
if (idx != a[pos]) {
for (int j = 1; j <= 30; j++) {
if (valid[j][idx]) f[j].upd(pos, 1);
if (valid[j][a[pos]]) f[j].upd(pos, -1);
}
}
a[pos] = idx;
} else {
int l, r, x, ok = 1;
scanf("%d%d%d", &l, &r, &x);
for (int j = 1; j <= 30 && ok; j++) {
ok = (f[j].query(r) - f[j].query(l - 1)) % x == 0;
}
puts(ok ? "YES" : "NO");
}
}
return 0;
}
某个人写的有节目效果的代码
#include <iostream>
#include <cstring>
#include <iomanip>
#include <algorithm>
#include <stack>
#include <queue>
#include <numeric>
#include <cassert>
#include <bitset>
#include <cstdio>
#include <vector>
#include <unordered_set>
#include <cmath>
#include <map>
#include <unordered_map>
#include <set>
#include <deque>
#include <tuple>
#include <random>
#include <array>
#define all(a) a.begin(), a.end()
#define cnt0(x) __builtin_ctz(x)
#define endl '\n'
#define ll long long
#define ull unsigned long long
#define cntone(x) __builtin_popcount(x)
#define db double
#define fs first
#define se second
#define AC main(void)
#define HYS std::ios::sync_with_stdio(false);std::cin.tie(0);std::cout.tie(0);
typedef std::pair<int, int > PII;
typedef std::pair<int, std::pair<int, int>> PIII;
typedef std::pair<ll, ll> Pll;
typedef std::pair<double, double> PDD;
using ld = double long;
const long double eps = 1e-9;
const int INF = 0x3f3f3f3f;
const int N = 6e5 + 10, M = 6e2 + 10;
int n, m, p;
int a[N];
int d1[] = {0, 0, 1, -1};
int d2[] = {1, -1, 0, 0};
struct Fenwick{
int maxm, cnt = 0;
std::vector<int> tr;
Fenwick(int n): tr(n + 1, 0) {maxm = n;}
inline int lowbit(int x) {return x & -x;}
inline void add(int x, int v){
for(int i = x; i <= maxm; i += lowbit(i)) tr[i] += v;
cnt += v;
}
inline int query(int x){
int res = 0;
for(int i = x; i; i -= lowbit(i)) res += tr[i];
return res;
}
inline int query(int l, int r){
return query(r) - query(l - 1);
}
inline int find_kmin(int k) {
int ans = 0, cnt = 0;
for (int i = 20; i >= 0; i--) {
ans += (1 << i);
if (ans >= maxm || cnt + tr[ans] >= k) ans -= (1 << i);
else cnt += tr[ans];
}
return ans + 1;
}
inline int find_kmax(int k) {
return find_kmin(cnt - k + 1);
}
};
int used[31][N];
inline void solve(){
std::random_device rd;
std::default_random_engine eng(rd());
std::uniform_int_distribution<int> distr(0, 1);
std::map<int, int> mp;
int idx = 0;
std::cin >> n >> m;
int pn = n;
for(int i = 1; i <= n; i ++){
std::cin >> a[i];
if(!mp[a[i]]) mp[a[i]] = ++ idx;
a[i] = mp[a[i]];
}
std::vector<std::array<int, 4>> q(m);
for(int i = 0; i < m; i ++){
auto &[op, l, r, v] = q[i];
std::cin >> op >> l >> r;
if(op == 2) std::cin >> v;
else{
if(!mp[r]) mp[r] = ++ idx;
r = mp[r];
}
}
Fenwick fk1(n);
Fenwick fk2(n);
Fenwick fk3(n);
Fenwick fk4(n);
Fenwick fk5(n);
Fenwick fk6(n);
Fenwick fk7(n);
Fenwick fk8(n);
Fenwick fk9(n);
Fenwick fk10(n);
Fenwick fk11(n);
Fenwick fk12(n);
Fenwick fk13(n);
Fenwick fk14(n);
Fenwick fk15(n);
Fenwick fk16(n);
Fenwick fk17(n);
Fenwick fk18(n);
Fenwick fk19(n);
Fenwick fk20(n);
Fenwick fk21(n);
Fenwick fk22(n);
Fenwick fk23(n);
Fenwick fk24(n);
Fenwick fk25(n);
Fenwick fk26(n);
Fenwick fk27(n);
Fenwick fk28(n);
Fenwick fk29(n);
Fenwick fk30(n);
n = mp.size();
for(int i = 1; i <= 30; i ++)
for(int j = 0; j < n; j ++)
used[i][j] = distr(eng);
for(int i = 1; i <= pn; i ++)
if(used[1][a[i]]) fk1.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[2][a[i]]) fk2.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[3][a[i]]) fk3.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[4][a[i]]) fk4.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[5][a[i]]) fk5.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[6][a[i]]) fk6.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[7][a[i]]) fk7.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[8][a[i]]) fk8.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[9][a[i]]) fk9.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[10][a[i]]) fk10.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[11][a[i]]) fk11.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[12][a[i]]) fk12.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[13][a[i]]) fk13.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[14][a[i]]) fk14.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[15][a[i]]) fk15.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[16][a[i]]) fk16.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[17][a[i]]) fk17.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[18][a[i]]) fk18.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[19][a[i]]) fk19.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[20][a[i]]) fk20.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[21][a[i]]) fk21.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[22][a[i]]) fk22.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[23][a[i]]) fk23.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[24][a[i]]) fk24.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[25][a[i]]) fk25.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[26][a[i]]) fk26.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[27][a[i]]) fk27.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[28][a[i]]) fk28.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[29][a[i]]) fk29.add(i, 1);
for(int i = 1; i <= pn; i ++)
if(used[30][a[i]]) fk30.add(i, 1);
for(int i = 0; i < m; i ++){
auto &[op, l, r, v] = q[i];
if(op == 1){
if(r == a[l]) continue;
if(used[1][a[l]]) fk1.add(l, -1);
if(used[1][r]) fk1.add(l, 1);
if(used[2][a[l]]) fk2.add(l, -1);
if(used[2][r]) fk2.add(l, 1);
if(used[3][a[l]]) fk3.add(l, -1);
if(used[3][r]) fk3.add(l, 1);
if(used[4][a[l]]) fk4.add(l, -1);
if(used[4][r]) fk4.add(l, 1);
if(used[5][a[l]]) fk5.add(l, -1);
if(used[5][r]) fk5.add(l, 1);
if(used[6][a[l]]) fk6.add(l, -1);
if(used[6][r]) fk6.add(l, 1);
if(used[7][a[l]]) fk7.add(l, -1);
if(used[7][r]) fk7.add(l, 1);
if(used[8][a[l]]) fk8.add(l, -1);
if(used[8][r]) fk8.add(l, 1);
if(used[9][a[l]]) fk9.add(l, -1);
if(used[9][r]) fk9.add(l, 1);
if(used[10][a[l]]) fk10.add(l, -1);
if(used[10][r]) fk10.add(l, 1);
if(used[11][a[l]]) fk11.add(l, -1);
if(used[11][r]) fk11.add(l, 1);
if(used[12][a[l]]) fk12.add(l, -1);
if(used[12][r]) fk12.add(l, 1);
if(used[13][a[l]]) fk13.add(l, -1);
if(used[13][r]) fk13.add(l, 1);
if(used[14][a[l]]) fk14.add(l, -1);
if(used[14][r]) fk14.add(l, 1);
if(used[15][a[l]]) fk15.add(l, -1);
if(used[15][r]) fk15.add(l, 1);
if(used[16][a[l]]) fk16.add(l, -1);
if(used[16][r]) fk16.add(l, 1);
if(used[17][a[l]]) fk17.add(l, -1);
if(used[17][r]) fk17.add(l, 1);
if(used[18][a[l]]) fk18.add(l, -1);
if(used[18][r]) fk18.add(l, 1);
if(used[19][a[l]]) fk19.add(l, -1);
if(used[19][r]) fk19.add(l, 1);
if(used[20][a[l]]) fk20.add(l, -1);
if(used[20][r]) fk20.add(l, 1);
if(used[21][a[l]]) fk21.add(l, -1);
if(used[21][r]) fk21.add(l, 1);
if(used[22][a[l]]) fk22.add(l, -1);
if(used[22][r]) fk22.add(l, 1);
if(used[23][a[l]]) fk23.add(l, -1);
if(used[23][r]) fk23.add(l, 1);
if(used[24][a[l]]) fk24.add(l, -1);
if(used[24][r]) fk24.add(l, 1);
if(used[25][a[l]]) fk25.add(l, -1);
if(used[25][r]) fk25.add(l, 1);
if(used[26][a[l]]) fk26.add(l, -1);
if(used[26][r]) fk26.add(l, 1);
if(used[27][a[l]]) fk27.add(l, -1);
if(used[27][r]) fk27.add(l, 1);
if(used[28][a[l]]) fk28.add(l, -1);
if(used[28][r]) fk28.add(l, 1);
if(used[29][a[l]]) fk29.add(l, -1);
if(used[29][r]) fk29.add(l, 1);
if(used[30][a[l]]) fk30.add(l, -1);
if(used[30][r]) fk30.add(l, 1);
a[l] = r;
}else{
bool flag = true;
if(fk1.query(l, r) % v) flag = false;
if(fk2.query(l, r) % v) flag = false;
if(fk3.query(l, r) % v) flag = false;
if(fk4.query(l, r) % v) flag = false;
if(fk5.query(l, r) % v) flag = false;
if(fk6.query(l, r) % v) flag = false;
if(fk7.query(l, r) % v) flag = false;
if(fk8.query(l, r) % v) flag = false;
if(fk9.query(l, r) % v) flag = false;
if(fk10.query(l, r) % v) flag = false;
if(fk11.query(l, r) % v) flag = false;
if(fk12.query(l, r) % v) flag = false;
if(fk13.query(l, r) % v) flag = false;
if(fk14.query(l, r) % v) flag = false;
if(fk15.query(l, r) % v) flag = false;
if(fk16.query(l, r) % v) flag = false;
if(fk17.query(l, r) % v) flag = false;
if(fk18.query(l, r) % v) flag = false;
if(fk19.query(l, r) % v) flag = false;
if(fk20.query(l, r) % v) flag = false;
if(fk21.query(l, r) % v) flag = false;
if(fk22.query(l, r) % v) flag = false;
if(fk23.query(l, r) % v) flag = false;
if(fk24.query(l, r) % v) flag = false;
if(fk25.query(l, r) % v) flag = false;
if(fk26.query(l, r) % v) flag = false;
if(fk27.query(l, r) % v) flag = false;
if(fk28.query(l, r) % v) flag = false;
if(fk29.query(l, r) % v) flag = false;
if(fk30.query(l, r) % v) flag = false;
std::cout << (flag ? "YES" : "NO") << '\n';
}
}
}
signed AC{
HYS
int _ = 1;
//std::cin >> _;
while (_ --)
solve();
return 0;
}