-
題意:
每個點的權值爲向後 箇中 的個數,給定 求最小權值,強制在線,空間 -
如果不強制在線的話,考慮按 加入答案算貢獻,線段樹維護就做完了
如果不卡空間的話,主席樹就做完了
聽大神 講了過後就會了下面空間 ,時間 的做法 -
考慮修改用差分表示,那麼就是一個點 +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;
}