对于w=100000,相当于没有w这个限制,直接主席树即可。
对于非强制在线的,可以考虑莫队算法,对值域分块,维护每个块小于等于w的数的个数,查询时暴力过去,直到发现答案在当前这个块里,停下来,再暴力,一次是O( n√ )。
但是现在强制在线了,how to do it?
还是可以暴力分块的。
对序列也分块。
设c[i][j][k]表示序列上的第i块到第j块在值域的第k块的数的个数(减去超过w次的)。
可以 O(n1.5) 预处理.
再设s[i][j]表示序列上的前i块中值为j的有多少个。
对于每一个询问[l..r],我们可以借助辅助数组c、s在 O(n√) 的时间里求出b[i],其中b[i]表示值域第i块的在区间[l..r]li一共有多少个出现次数不超过w的数,于是我可以暴力扫过去,直到发现答案在当前块里,再暴力,此时在借助辅助数组s,可以求出每个数出现了多少次。
总复杂度是 O(n1.5) 的,空间也是这么大的。
Code:
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i++)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 100005, M = 320;
int n, w, type, ans, Q, x, y, z, a[N], c[M][M][M], s[M][N], t[N], b[M], bz[N];
int num[N], l[M], r[M];
void Init() {
scanf("%d %d %d %d", &n, &w, &Q, &type);
w ++;
fo(i, 1, n) scanf("%d", &a[i]);
fo(i, 0, n) {
num[i] = num[i - 1] + (i % M == 0);
if(i % M == 0) {
l[num[i]] = i;
r[num[i - 1]] = i - 1;
}
}
r[num[n]] = n;
}
void Build() {
fo(i, 1, num[n]) {
memset(t, 0, sizeof(t));
fo(j, i, num[n]) {
if(j != i) fo(k, 1, num[n]) c[i][j][k] = c[i][j - 1][k];
fo(k, l[j], r[j]) {
t[a[k]] ++;
if(t[a[k]] <= w) {
c[i][j][num[a[k]]] ++;
if(t[a[k]] == w) c[i][j][num[a[k]]] -= w;
}
}
}
}
fo(i, 1, num[n]) {
fo(j, 0, n) s[i][j] = s[i - 1][j];
fo(j, l[i], r[i]) s[i][a[j]] ++;
}
}
void xiu(int i) {
if(!bz[a[i]]) {
bz[a[i]] = 1;
if(num[x] + 1 <= num[y] - 1)
t[a[i]] = s[num[y] - 1][a[i]] - s[num[x]][a[i]];
}
t[a[i]] ++;
if(t[a[i]] <= w) {
b[num[a[i]]] ++;
if(t[a[i]] == w) b[num[a[i]]] -= w;
}
}
void End() {
memset(t, 0, sizeof(t));
for(; Q; Q --) {
scanf("%d %d %d", &x, &y, &z);
x ^= ans * type; y ^= ans * type; z ^= ans * type;
ans = n;
fo(i, 1, num[n]) b[i] = c[num[x] + 1][num[y] - 1][i];
if(num[x] != num[y]) {
fo(i, x, r[num[x]]) xiu(i);
fo(i, l[num[y]], y) xiu(i);
} else {
fo(i, x, y) xiu(i);
}
fo(i, 1, num[n]) {
z -= b[i];
if(z <= 0) {
z += b[i];
fo(j, l[i], r[i]) {
if(!bz[j]) {
bz[j] = 1;
if(num[x] + 1 <= num[y] - 1)
t[j] = s[num[y] - 1][j] - s[num[x]][j];
}
if(t[j] < w) z -= t[j];
if(z <= 0) {
ans = j;
fo(k, l[i], j) bz[k] = t[k] = 0;
break;
}
}
break;
}
}
fo(i, x, r[num[x]]) bz[a[i]] = t[a[i]] = 0;
fo(i, l[num[y]], y) bz[a[i]] = t[a[i]] = 0;
printf("%d\n", ans);
}
}
int main() {
freopen("kth.in", "r", stdin);
freopen("kth.out", "w", stdout);
Init();
Build();
End();
}