#P14513. [NFLSPC #8] 追忆desuwa

[NFLSPC #8] 追忆desuwa

题目背景

Zhengxu Sakiko 是一位著名的算法竞赛选手。只不过他由于记性太差经常忘记学过的算法。

这就是为什么他常常追忆过去。

题目描述

请注意本题特殊的空间限制。

给定 mm 个三元组 (l,r,v)(l,r,v)

qq 个操作,每次给出 x,yx,y,表示查询 lxrl\le x\le rvyv\le y 的三元组中,vv 的最大值是多少。

如果不存在满足条件的三元组,输出 00

本题强制在线。

输入格式

第一行两个整数 m,qm,q

接下来 mm 行每行三个整数表示一组 (l,r,v)(l,r,v)

接下来 qq 行每行两个整数 p,qp,q 表示当前询问满足 x=pans,y=qansx=p\oplus ans,y=q\oplus ans,其中 \oplus 表示异或操作,ansans 表示上次询问的答案和 22112^{21}-1 按位与的值。初始的 ansans00

输出格式

对于每个询问输出一行表示答案。

5 5
3 5 3
4 5 10
3 4 2
1 4 13
1 1 6
1 6
7 11
9 14
2 1
5 14
6
13
3
0
10
15 15
3 9 9
3 5 10
8 15 10
4 6 4
8 13 6
3 7 0
11 11 11
8 10 11
3 3 14
3 15 13
4 15 9
6 11 7
4 5 12
6 12 10
10 10 14
9 5
1 5
8 11
14 9
8 14
3 11
7 1
4 3
3 1
12 15
9 4
13 15
0 3
13 12
6 13
0
0
11
0
13
0
0
0
0
13
9
4
4
7
0

提示

数据范围

子任务名称 子任务编号 分值 限制
用脚维护 1 25 空间限制为 2048MiB
不劳而获 2 q3×104q\le 3\times 10^4
数据结构大师 3 q105q\le 10^5
我即是虚像 4 无特殊限制

对于所有数据:$1\le m,q\leq 10^6,1\le l\le r\le 2\times 10^6, 0\le v<2^{31}, 1\leq x\leq 2\times 10^6, 0\leq y< 2^{31}$。

提示

建议从附件下载小 Z 的追忆,这些回忆可以帮助你解决本题。

::::info[另外,这里有一份小 Z 编写的区间第 kk 小值的代码,可能对你有所帮助。]

#include <bits/stdc++.h>
using namespace std;
constexpr int Spp{1<<20},S2{1<<20};
char buf[Spp],*p1,*p2,buf2[S2],*l2=buf2,_st[22];
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,Spp,stdin),p1==p2)?EOF:*p1++)
#define putchar(c) (l2==buf2+S2&&(fwrite(buf2,1,S2,stdout),l2=buf2),*l2++=(c))
template <typename T>
void read(T &x) {
    char c;int f{1};
    do x=(c=getchar())^48;
    while (!isdigit(c)&&c!='-');
    if (x==29) f=-1,x=0;
    while (isdigit(c=getchar()))
        x=(x*10)+(c^48);
    x*=f;
}
template <typename T,typename ...Args>
void read(T& x,Args&... args) {read(x);read(args...);}
template<typename T>
void write(T x,char c='\n') {
    if (x<0) putchar('-'),x*=-1;
    int tp=0;
    do _st[++tp]=x%10; while (x/=10);
    while (tp) putchar(_st[tp--]+'0');
    putchar(c);
}
struct OI{~OI(){fwrite(buf2,1,l2-buf2,stdout);}}oi;
using LL=unsigned long long;
// wavelet
struct bits {
	vector<LL> bl;
	vector<int> c;
	void resize(int num) {
		bl.resize(((num+1)>>6)+1);
		c.resize(bl.size());
	}
	void set(int i,LL val) {bl[i>>6]|=(val<<(i&63));}
	void build() {
		for (int i=1;i<bl.size();++i)
			c[i]=c[i-1]+popcount(bl[i-1]);
	}
	int rk1(int i) {return c[i>>6]+popcount(bl[i>>6]&((1uLL<<(i&63))-1));}
	int rk0(int i) {return i-rk1(i);}
};
struct wavelet {
	int h;
	vector<bits> B;
	vector<int> pos;
	void init(vector<int>& v) {
        h=__lg(*max_element(v.begin(),v.end()))+1;
		B.resize(h);pos.resize(h);
		for (int i=0;i<h;++i) {
			B[i].resize(v.size());
			for (int j=0;j<v.size();++j)
				B[i].set(j,(v[j]>>(h-i-1)&1));
			B[i].build();
			pos[i]=stable_partition(v.begin(),v.end(),[&](int c){
				return !(c>>(h-i-1)&1);
			})-v.begin();
		}
	}
	int qry(int i,int j,int k,int l,int r,int x) {
		if (i==j) return 0;
		if (r==l+1) return l;
		int mid=l+r>>1;
        int L{B[x].rk0(i)},R{B[x].rk0(j)};
        if (R-L>=k) return qry(L,R,k,l,mid,x+1);
        else return qry(pos[x]+B[x].rk1(i),pos[x]+B[x].rk1(j),k-(R-L),mid,r,x+1);
	}
} tr;
int main() {
    int n,m;read(n,m);
    vector<int> a(n);
    for (int i=0;i<n;++i) read(a[i]);
    tr.init(a);
    while (m--) {
        int l,r,k;read(l,r,k);
        write(tr.qry(l-1,r,k,0,1<<tr.h,0));
    }
    return 0;
}

::::