- 题意:
每个点的权值为向后个中
的个数,给定
求最小权值,强制在线,空间
 - 如果不强制在线的话,考虑按
加入答案算贡献,线段树维护就做完了
如果不卡空间的话,主席树就做完了
听大神讲了过后就会了下面空间
,时间
的做法
 - 考虑修改用差分表示,那么就是一个点 +1,一个点 - 1,维护前缀最大值,那么一个点最多被修改 2 次
注意到这样的话一个大小为的块的状态数是
的,直接记下即可
需要维护块的每个时间的和,块的前缀最大值
散块查询可以先求出块头的答案,然后差分递推
现在的问题是要找到每个块对应的时间,本来想走人的,结果又被
教育了
考虑一长为的序列,每个点有个颜色,颜色数
那么直接继续分块,预处理每种颜色在的时间处的取值就可以严格
分块怎么套都是!
 
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(){
  
  freopen("music.in","r",stdin);
  freopen("music.out","w",stdout);
  
  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;
}                
                










