W
e
l
c
o
m
e
: )

CF1746F Kazaee 题解

CF1746F Kazaee 题解

题目描述

CF1746F Kazaee

题目解法

看到题目能想到一个相当劣的树状数组做法:先离散化,然后对每个数开个树状数组,每次查询区间内每个数的个数。

这个做法相当劣,修改 \(O(\log{n})\),查询 \(O(n\log n)\),总的复杂度为 \(O(n^2 \log n)\) 无法通过本题。(空间也开不下)

好像还有一个 \(O(n^{\frac{5}{3} }\log n)\) 的莫队做法,但是也过不去...

所以就只能考虑乱搞。

我们考虑一个区间 \([l,r]\),如果每个出现过的正整数的出现次数都是 \(k\) 的倍数,那么一定有:

\[\sum^r_{i=l} a_i \equiv 0 \pmod k \]

但是上述条件只是一个必要条件,并不是充分条件。

其错误率大概是 \(\frac{1}{k}\)

考虑随机化。

序列 \(b_j\) 是将 \(a\) 序列中每个值随机分配了一个值域中的新值后生成的序列。

比如 \(a=\{1,2,2,4,3\}\),那么我们令 \(b_1=\{2,1,1,5,4\}\)\(b_2, b_3\) 同理。

如果对于所有的 \(T\)\(b_j\),其均满足:

\[\sum^r_{i=l} b_{j,i}\equiv 0 \pmod k \]

那么判断的错误率就是 \(\frac{1}{k^T}\)

\(T\) 的取值就自行调参,\(T\) 过大会导致超时,\(T\) 过小会判断错误。

实现方法就是开 \(T\) 组树状数组。

用结构体和 vector 的树状数组被卡了,请各位注意卡常

Code

#include<bits/stdc++.h>
using namespace std;
#define maxn 300005
#define i64 long long
const int T=30;

template< typename T >inline void read(T &x)
{
	char c=getchar();x=0;int f=0;
	for(;!isdigit(c);c=getchar()) f|=(c=='-');
	for(;isdigit(c);c=getchar()) x=((x<<3)+(x<<1)+(c^48));
	x=f?-x:x;
}

template< typename T >inline void write(T x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
}

template< typename T,typename ... Args > 
inline void read(T &_x, Args &... args) 
{read(_x), read(args...);}

template< typename T,typename ... Args > 
inline void write(T _x, Args ... args) 
{ write(_x), write(args...);}

unordered_map<int, int> hsh;

int cnt=0;

i64 ta[T][maxn];
int dic[T][maxn<<1];

int val(int x, int t) {return dic[t][hsh.count(x)?(hsh[x]):(hsh[x]=++cnt)];}
void modify(int i, int v, int t) {for(;i<maxn;i+=i&-i) ta[t][i]+=v;}
i64 __qry(int i, int t) {i64 r=0; for(;i;i-=i&-i) r+=ta[t][i]; return r;}
i64 query(int l, int r, int t) {return __qry(r, t)-__qry(l-1, t);}

int lis[maxn];  

#define rng for(int t=0;t<T;t++)

int main()
{
    srand(time(0));
    int n,q;
    read(n, q);
    rng for(int j=1;j<=n+q;j++) dic[t][j]=j;
    rng random_shuffle(dic[t]+1, dic[t]+1+n+q); 
    // 赋随机值的方法被卡了,所以用 random_shuffle()

    for(int i=1;i<=n;i++)
    {
        read(lis[i]);
        rng modify(i, val(lis[i], t), t);
    }
    while(q--)
    {
        int opt, l, r, k;
        read(opt);
        if(opt==1)
        {
            read(l, r);
            rng modify(l, val(r, t)-val(lis[l], t), t);
            lis[l]=r;
        }
        else
        {
            read(l, r, k);
            if((r-l+1)%k) {puts("NO");continue;}
            int tag=0;
            rng if(query(l, r, t)%k) {tag=1; break;}
            puts(tag?"NO":"YES");
        }
    }
}
posted @ 2024-08-25 20:56  Jimmy-LEEE  阅读(34)  评论(0)    收藏  举报