-
题意:
每个点的权值为向后 个中 的个数,给定 求最小权值,强制在线,空间 -
如果不强制在线的话,考虑按 加入答案算贡献,线段树维护就做完了
如果不卡空间的话,主席树就做完了
听大神 讲了过后就会了下面空间 ,时间 的做法 -
考虑修改用差分表示,那么就是一个点 +1,一个点 - 1,维护前缀最大值,那么一个点最多被修改 2 次
注意到这样的话一个大小为 的块的状态数是 的,直接记下即可
需要维护块的每个时间的和,块的前缀最大值
散块查询可以先求出块头的答案,然后 差分递推
现在的问题是要找到每个块对应的时间,本来想 走人的,结果又被 教育了
考虑一长为 的序列,每个点有个颜色,颜色数
那么直接继续分块,预处理每种颜色在 的时间处的取值就可以严格
分块怎么套都是 !
#include<bits/stdc++.h>
#define cs const
#define pb push_back
using namespace std;
namespace IO{
cs int Rlen=1<<20|1;
inline char gc(){
static char buf[Rlen],*p1,*p2;
(p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin));
return p1==p2?EOF:*p1++;
}
int read(){
int x=0; char c=gc(); bool f=false;
while(!isdigit(c)) f=c=='-', c=gc();
while(isdigit(c)) x=(((x<<2)+x)<<1)+(c^48), c=gc();
return f?-x:x;
}
} using namespace IO;
typedef pair<int, int> pi;
typedef vector<int> poly;
cs int N = 2e5 + 50, M = 550;
cs int INF = 1e9 + 7;
int n, S, m, q, T, a[N], blk[N];
int L[M], R[M], cnt;
int ct[M], s[N], ps[M];
poly mn[M], sm[M];
namespace sub{
cs int N = ::N << 1;
cs int M = 850;
struct node{ int a, b, c; };
bool operator < (cs node &a, cs node &b){ return a.a < b.a; }
node c[N]; int len, S, ct;
int p[M][M], L[M], R[M]; int blk[N];
void pre_work(){
S=sqrt(len);
for(int i=1; i<=len; i++) blk[i]=(i-1)/S+1;
for(int i=1; i<=len; i+=S) ++ct, L[ct]=i, R[ct]=i+S-1; R[ct]=n;
static int tmp[M]; // current
for(int i=1,t=1; i<=len; i++){
node nw = c[i]; tmp[nw.b]=nw.c;
if(i==R[t]){ for(int j=1; j<=cnt; j++) p[j][t]=tmp[j]; ++t; }
}
}
void work(int x){
int t = lower_bound(c+1, c+len+1, (node){x,0,0}) - (c+1), b = blk[t];
for(int i=1; i<=cnt; i++) ps[i]=p[i][b-1];
for(int i=L[b]; i<=t; i++){ node nw = c[i]; ps[nw.b]=nw.c; }
}
}
void Add(int p, int v, int a){
if(p>n) return;
int b = blk[p]; int nw = INF;
sm[b].pb(sm[b][ct[b]] + v); ++ct[b];
for(int i=p; i<=R[b]; i++) s[i]+=v;
for(int i=L[b]; i<=R[b]; i++) nw=min(nw,s[i]);
mn[b].pb(nw); sub :: c[++sub::len] = {a,b,ct[b]};
}
int subwork(int v, int S, int l, int r){
int as = INF, now = v;
for(int i=S; i<=r; i++){
if(i>=l) as = min(as,now);
now -= (i>0&&a[i]<T); now += (a[i+m]<T);
} return as;
}
int work(int l, int r){
int as=INF, Sm=0, u=0, v=0;
for(int i=1; i<=cnt; i++){
if(i==blk[l]) u=Sm;
if(i==blk[r]){ v=Sm; break; }
if(l<=L[i]&&R[i]<=r) as=min(as,Sm+mn[i][ps[i]]);
Sm+=sm[i][ps[i]];
}
if(blk[l] == blk[r]) return min(as, subwork(u,L[blk[l]]-1,l,r));
if(l>L[blk[l]]) as = min(as, subwork(u,L[blk[l]]-1,l,R[blk[l]]));
as = min(as, subwork(v,L[blk[r]]-1,L[blk[r]],r)); return as;
}
int main(){
#ifdef FSYolanda
freopen("music.in","r",stdin);
freopen("music.out","w",stdout);
#endif
n=read(), m=read(); S=sqrt(n); static int id[N];
for(int i=1; i<=n; i++) a[i]=read(), id[i]=i;
sort(id+1, id+n+1, [](cs int &i, cs int &j){ return a[i] < a[j]; });
blk[0]=1; for(int i=1; i<=n; i++) blk[i]=(i-1)/S+2; ++cnt;
for(int i=1; i<=n; i+=S) ++cnt, L[cnt]=i, R[cnt]=i+S-1; R[cnt]=n;
for(int i=1; i<=cnt; i++) sm[i].pb(0), mn[i].pb(0);
for(int i=1; i<=n; i++){
int u=id[i];
Add(max(0,u-m+1),1,a[u]); Add(u+1,-1,a[u]);
} sub :: pre_work();
q=read(); int as=0;
while(q--){
int l=read(), r=read(); T=read()^as;
sub :: work(T);
cout << (as=work(l,r)) << '\n';
} return 0;
}