题解 区间第 k 小
考虑树套树
外层线段树对颜色开,在上面跑线段树二分
内层线段树对序列下标开,存外层线段树节点所包含的颜色在序列上的所有出现位置
然后在内层线段树上扫描线
- 关于形如「出现次数 \(\leqslant w\) 的数的出现次数之和」或给它再带个权的限制:
一个常见处理方式是扫描线,从右到左前 \(w\) 个权值为 1,第 \(w+1\) 个权值为 \(-w\)
那么把扫描线的过程可持久化下来即可
因为内存访问极其不连续的原因常数极大
大到完全几乎完全没法过的程度
复杂度 \(O(n\log^2 n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, w, q, typ;
int a[N];
#define ls(p) tree[p].lson
#define rs(p) tree[p].rson
#define sum(p) tree[p].sum
// namespace force{
// int sta[N], cnt[N], top;
// void solve() {
// for (int i=1,l,r,k,lst=0; i<=q; ++i) {
// l=read()^(lst*typ); r=read()^(lst*typ); k=read()^(lst*typ); top=0;
// for (int j=0; j<=n; ++j) cnt[j]=0;
// for (int j=l; j<=r; ++j) ++cnt[a[j]];
// for (int j=l; j<=r; ++j)
// if (cnt[a[j]]<=w) sta[++top]=a[j];
// else sta[++top]=n;
// sort(sta+1, sta+top+1);
// printf("%d\n", lst=sta[k]);
// }
// }
// }
// namespace task1{
// int *rot, *lson, *rson, *cnt, tot;
// void upd(int& p1, int p2, int tl, int tr, int pos, int val) {
// p1=++tot; ls(p1)=ls(p2); rs(p1)=rs(p2);
// if (tl==tr) {cnt[p1]=cnt[p2]+val; return ;}
// int mid=(tl+tr)>>1;
// if (pos<=mid) upd(ls(p1), ls(p2), tl, mid, pos, val);
// else upd(rs(p1), rs(p2), mid+1, tr, pos, val);
// cnt[p1]=cnt[ls(p1)]+cnt[rs(p1)];
// }
// int kth(int p1, int p2, int tl, int tr, int k) {
// if (tl==tr) return tl;
// int mid=(tl+tr)>>1, tem=cnt[ls(p2)]-cnt[ls(p1)];
// if (k<=tem) return kth(ls(p1), ls(p2), tl, mid, k);
// else return kth(rs(p1), rs(p2), mid+1, tr, k-tem);
// }
// void solve() {
// rot=new int[N]; cnt=new int[50*N];
// lson=new int[50*N]; rson=new int[50*N];
// memset(rot, 0, sizeof(int)*N);
// memset(cnt, 0, sizeof(int)*50*N);
// memset(lson, 0, sizeof(int)*50*N);
// memset(rson, 0, sizeof(int)*50*N);
// for (int i=1; i<=n; ++i) upd(rot[i], rot[i-1], 0, n, a[i], 1);
// for (int i=1,l,r,k,lst=0; i<=q; ++i) {
// l=read()^(lst*typ); r=read()^(lst*typ); k=read()^(lst*typ);
// printf("%d\n", lst=kth(rot[l-1], rot[r], 0, n, k));
// }
// }
// }
// namespace task2{
// vector<int> s;
// int **pre, *siz, *rot, *lson, *rson, *cnt, tot;
// void upd(int& p1, int p2, int tl, int tr, int pos, int val) {
// p1=++tot; ls(p1)=ls(p2); rs(p1)=rs(p2);
// if (tl==tr) {cnt[p1]=cnt[p2]+val; return ;}
// int mid=(tl+tr)>>1;
// if (pos<=mid) upd(ls(p1), ls(p2), tl, mid, pos, val);
// else upd(rs(p1), rs(p2), mid+1, tr, pos, val);
// cnt[p1]=cnt[ls(p1)]+cnt[rs(p1)];
// }
// int kth(int p1, int p2, int tl, int tr, int k) {
// if (tl==tr) return tl;
// int mid=(tl+tr)>>1, tem=cnt[ls(p2)]-cnt[ls(p1)];
// if (k<=tem) return kth(ls(p1), ls(p2), tl, mid, k);
// else return kth(rs(p1), rs(p2), mid+1, tr, k-tem);
// }
// void upd(int p, int tl, int tr, int pos, int val) {
// if (tl==tr) {cnt[p]+=val; return ;}
// int mid=(tl+tr)>>1;
// if (pos<=mid) upd(ls(p), tl, mid, pos, val);
// else upd(rs(p), mid+1, tr, pos, val);
// cnt[p]=cnt[ls(p)]+cnt[rs(p)];
// }
// void solve() {
// siz=new int[N];
// rot=new int[N]; cnt=new int[50*N];
// lson=new int[50*N]; rson=new int[50*N];
// memset(siz, 0, sizeof(int)*N);
// memset(rot, 0, sizeof(int)*N);
// memset(cnt, 0, sizeof(int)*50*N);
// memset(lson, 0, sizeof(int)*50*N);
// memset(rson, 0, sizeof(int)*50*N);
// for (int i=1; i<=n; ++i) upd(rot[i], rot[i-1], 0, n, a[i], 1), ++siz[a[i]];
// for (int i=0; i<n; ++i) if (siz[i]>w) s.pb(i);
// pre=new int*[s.size()+10];
// for (int i=0; i<s.size(); ++i) {
// pre[i]=new int[n+10];
// memset(pre[i], 0, sizeof(int)*(n+10));
// for (int j=1; j<=n; ++j) if (a[j]==s[i]) ++pre[i][j];
// for (int j=1; j<=n; ++j) pre[i][j]+=pre[i][j-1];
// }
// for (int i=1,l,r,k,lst=0; i<=q; ++i) {
// l=read()^(lst*typ); r=read()^(lst*typ); k=read()^(lst*typ);
// int all=r-l+1;
// for (int j=0; j<s.size(); ++j) if (pre[j][r]-pre[j][l-1]>w) {
// all-=pre[j][r]-pre[j][l-1];
// upd(rot[r], 0, n, s[j], pre[j][l-1]-pre[j][r]);
// }
// if (all<k) printf("%d\n", lst=n);
// else printf("%d\n", lst=kth(rot[l-1], rot[r], 0, n, k));
// for (int j=0; j<s.size(); ++j) if (pre[j][r]-pre[j][l-1]>w)
// upd(rot[r], 0, n, s[j], pre[j][r]-pre[j][l-1]);
// }
// }
// }
// namespace task3{
// int lst[N], rot[N], buc[N], del[N];
// namespace in{
// int rot[N*200], lson[N*200], rson[N*200], cnt[N*200], tot;
// void upd(int& p1, int p2, int tl, int tr, int pos, int val) {
// p1=++tot; ls(p1)=ls(p2); rs(p1)=rs(p2);
// if (tl==tr) {cnt[p1]=cnt[p2]+val; return ;}
// int mid=(tl+tr)>>1;
// if (pos<=mid) upd(ls(p1), ls(p2), tl, mid, pos, val);
// else upd(rs(p1), rs(p2), mid+1, tr, pos, val);
// cnt[p1]=cnt[ls(p1)]+cnt[rs(p1)];
// }
// int query(int p, int tl, int tr, int ql, int qr) {
// if (ql<=tl&&qr>=tr) return cnt[p];
// int mid=(tl+tr)>>1, ans=0;
// if (ql<=mid) ans+=query(ls(p), tl, mid, ql, qr);
// else ans+=query(rs(p), mid+1, tr, ql, qr);
// return ans;
// }
// int qcnt(int p, int l, int r) {return query(p, 0, n, l, r);}
// }
// namespace out{
// int rot[N*200], lson[N*200], rson[N*200], cnt[N*200], dat[N*200], tot, itst;
// void upd(int& p1, int p2, int tl, int tr, int col, int pos, int val) {
// p1=++tot; ls(p1)=ls(p2); rs(p1)=rs(p2);
// in::upd(dat[p1], dat[p2], 0, n, pos, val);
// if (tl==tr) return ;
// int mid=(tl+tr)>>1;
// if (col<=mid) upd(ls(p1), ls(p2), tl, mid, col, pos, val);
// else upd(rs(p1), rs(p2), mid+1, tr, col, pos, val);
// }
// int kth(int p1, int p2, int tl, int tr, int lim, int k) {
// // cout<<"kth: "<<tl<<' '<<tr<<' '<<lim<<' '<<k<<endl;
// if (tl==tr) return tl;
// int mid=(tl+tr)>>1, tem=in::qcnt(dat[ls(p2)], 0, lim)-in::qcnt(dat[ls(p1)], 0, lim);
// // cout<<"mid: "<<mid<<endl;
// // cout<<"tem: "<<tem<<endl;
// if (k<=tem) return kth(ls(p1), rs(p2), tl, mid, lim, k);
// else return kth(rs(p1), rs(p2), mid+1, tr, lim, k-tem);
// }
// int upd(int col, int pos, int val) {
// ++itst;
// upd(rot[itst], rot[itst-1], 0, n, col, pos, val);
// return itst;
// }
// int qcnt(int id, int lim) {
// if (!lim) return 0;
// --lim;
// return in::qcnt(dat[rot[id]], 0, lim);
// }
// int kth(int idl, int idr, int l, int k) {
// --l;
// return kth(rot[idl], rot[idr], 0, n, l, k);
// }
// }
// void solve() {
// for (int i=1; i<=n; ++i) {
// if (lst[a[i]]) out::upd(a[i], del[lst[a[i]]], -1);
// rot[i]=out::upd(a[i], lst[a[i]], 1);
// del[i]=lst[a[i]];
// lst[a[i]]=i;
// }
// for (int i=1,l,r,k,lst=0; i<=q; ++i) {
// l=read()^(lst*typ); r=read()^(lst*typ); k=read()^(lst*typ);
// if (out::qcnt(rot[r], l)-out::qcnt(rot[l-1], l)<k) printf("%d\n", lst=n);
// else printf("%d\n", lst=out::kth(rot[l-1], rot[r], l, k));
// }
// }
// }
namespace task{
bool vis[N];
#define tl(p) tl[p]
#define tr(p) tr[p]
int sta[N], tot, top;
pair<int, int> sta2[N];
struct tr{int lson, rson, sum;}tree[N*500];
int **que[N<<2], *now[N<<2], *dat[N<<2], *rot[N<<2];
int tl[N<<2], tr[N<<2], siz[N<<2], vsiz[N<<2], cnt[N];
#define pushup(p) sum(p)=sum(ls(p))+sum(rs(p))
void upd(int& p1, int p2, int tl, int tr, int pos, int val) {
sta[++top]=p1=++tot;
while (1) {
ls(p1)=ls(p2); rs(p1)=rs(p2);
if (tl==tr) {sum(p1)=sum(p2)+val; break;}
int mid=(tl+tr)>>1;
if (pos<=mid) ls(p1)=sta[++top]=++tot, p1=tot, p2=ls(p2), tr=mid;
else rs(p1)=sta[++top]=++tot, p1=tot, p2=rs(p2), tl=mid+1;
}
for (--top; top; --top) pushup(sta[top]);
p1=sta[1];
}
int query(int p, int tl, int tr, int ql, int qr) {
int ans=0, mid;
sta[++top]=p; sta2[top]={tl, tr}; vis[top]=0;
while (top) {
p=sta[top]; tl=sta2[top].fir; tr=sta2[top].sec;
if (ql<=tl&&qr>=tr) {--top; ans+=sum(p); continue;}
mid=(tl+tr)>>1;
if (!vis[top]&&ql<=mid&&ls(p)) {
vis[top]=1;
sta[++top]=ls(p); sta2[top]={tl, mid}; vis[top]=0;
continue;
}
--top;
if (qr>mid&&rs(p))
sta[++top]=rs(p), sta2[top]={mid+1, tr}, vis[top]=0;
}
return ans;
}
void build(int p, int l, int r) {
tl(p)=l; tr(p)=r;
now[p]=new int[r-l+1]-l;
que[p]=new int*[r-l+1]-l;
for (int i=l; i<=r; ++i) now[p][i]=0;
for (int i=l; i<=r; ++i) que[p][i]=new int[cnt[i]+1];
if (l==r) {
siz[p]=cnt[l];
dat[p]=new int[siz[p]+1];
rot[p]=new int[siz[p]+1];
dat[p][0]=rot[p][0]=0;
return ;
}
int mid=(l+r)>>1;
if (l<=mid) build(p<<1, l, mid);
if (r>mid) build(p<<1|1, mid+1, r);
siz[p]=siz[p<<1]+siz[p<<1|1];
dat[p]=new int[siz[p]+1];
rot[p]=new int[siz[p]+1];
dat[p][0]=rot[p][0]=0;
}
void upd(int p, int pos, int val) {
int tem;
dat[p][++vsiz[p]]=val;
que[p][pos][++now[p][pos]]=vsiz[p];
upd(tem, rot[p][vsiz[p]-1], 1, siz[p], vsiz[p], 1);
if (now[p][pos]>=w+2)
upd(tem, tem, 1, siz[p], que[p][pos][now[p][pos]-w-1], w);
if (now[p][pos]>=w+1)
upd(tem, tem, 1, siz[p], que[p][pos][now[p][pos]-w], -w-1);
rot[p][vsiz[p]]=tem;
if (tl(p)==tr(p)) return ;
int mid=(tl(p)+tr(p))>>1;
if (pos<=mid) upd(p<<1, pos, val);
else upd(p<<1|1, pos, val);
}
int qcnt(int p, int l, int r, int k) {
int id=upper_bound(dat[p], dat[p]+vsiz[p]+1, r)-dat[p]-1;
l=lower_bound(dat[p], dat[p]+vsiz[p]+1, l)-dat[p];
return query(rot[p][id], 1, siz[p], l, id);
}
int kth(int p, int l, int r, int k) {
// cout<<"kth: "<<tl(p)<<' '<<tr(p)<<' '<<k<<endl;
if (tl(p)==tr(p)) return tl(p);
int tem=qcnt(p<<1, l, r, k);
// cout<<"mid: "<<((tl(p)+tr(p))>>1)<<endl;
// cout<<"tem: "<<tem<<endl;
if (k<=tem) return kth(p<<1, l, r, k);
else return kth(p<<1|1, l, r, k-tem);
}
void solve() {
for (int i=1; i<=n; ++i) ++cnt[a[i]];
build(1, 0, n);
for (int i=1; i<=n; ++i) upd(1, a[i], i);
for (int i=1,l,r,k,lst=0; i<=q; ++i) {
l=read()^(lst*typ); r=read()^(lst*typ); k=read()^(lst*typ);
printf("%d\n", lst=kth(1, l, r, k));
}
// cout<<"tot: "<<tot<<endl;
}
}
signed main()
{
freopen("kth.in", "r", stdin);
freopen("kth.out", "w", stdout);
n=read(); w=read(); q=read(); typ=read();
for (int i=1; i<=n; ++i) a[i]=read();
// force::solve();
// if (w==n) task1::solve();
// else task2::solve();
// task3::solve();
task::solve();
return 0;
}