题意:每次操作将区间颜色置为x,要求可以查询某个颜色出现次数,强制在线,求最后出现次数最多的颜色的次数。
分析:考虑分块做法。
对于每个块记录一个laz,laz为0表示这个块中的颜色不唯一,否则表示该颜色。
更新时两端暴力更新,若整块的laz不为0,直接O(1)得到,否则暴力更新。
分析一下复杂度,两端暴力更新O(n^1/2),laz不为0的块O(1),laz为0的块O(n^1/2)。
同时每次更新仅仅会产生2个laz为0的块,当laz为0的块经过一次暴力更新后,laz必然不为0,所以总共暴力更新整块的次数不会超过2n次。所以复杂度O(n*sqrt(n))。
#include <bits/stdc++.h>
using namespace std;
const int mod = 1e9 + 7;
int mat, num;
int a[100004];
int L[350], R[350];
int col[100004];
int laz[350];
void upd(int l, int r, int x) {
int st = l / mat + 1;
int ed = r / mat + 1;
if(st == ed){
if(laz[st])
for (int i = L[st]; i <= R[st]; ++i) {
a[i] = laz[st];
}
laz[st]=0;
for (int i = l; i <= r; ++i) {
col[a[i]]--;
col[x]++;
a[i]=x;
}
return;
}
st ++;
ed --;
for (int i = st; i <= ed; ++i) {
if (laz[i]) {
col[laz[i]] -= R[i] - L[i] + 1;
col[x] += R[i] - L[i] + 1;
laz[i] = x;
} else {
for (int j = L[i]; j <= R[i]; ++j) {
col[a[j]]--;
col[x]++;
a[j] = x;
}
laz[i] = x;
}
}
if (laz[st - 1])
for (int i = L[st - 1]; i <= R[st - 1]; ++i) {
a[i] = laz[st - 1];
}
laz[st - 1] = 0;
if (laz[ed + 1])
for (int i = L[ed + 1]; i <= R[ed + 1]; ++i) {
a[i] = laz[ed + 1];
}
laz[ed + 1] = 0;
for (int i = l; i < L[st]; ++i) {
col[a[i]]--;
col[x]++;
a[i] = x;
}
for (int i = R[ed]+1; i <= r; ++i) {
col[a[i]]--;
col[x]++;
a[i] = x;
}
}
int main() {
int l, c, n;
memset(col, 0, sizeof(col));
scanf("%d%d%d", &l, &c, &n);
mat = sqrt(l);
num = (l + mat - 1) / mat;
for (int i = 1; i <= num; ++i) {
laz[i] = 1;
L[i] = (i - 1) * mat;
R[i] = i * mat - 1;
}
for (int i = 0; i < l; ++i) {
a[i] = 1;
}
R[num] = l - 1;
col[1] = l;
for (int i = 0; i < n; ++i) {
long long p, x, a, b;
scanf("%lld%lld%lld%lld", &p, &x, &a, &b);
long long s = col[p];
long long m1 = (a + s * s % l) % l;
long long m2 = (a + (s + b) * (s + b) % l) % l;
if (m1 > m2)swap(m1, m2);
upd(m1, m2, x);
}
int ans = 0;
for (int i = 1; i <= c; ++i) {
ans = max(ans,col[i]);
}
cout<<ans<<endl;
}