四猫子树

其实如果你去看原版四毛子你可以发现它是不依赖可重复贡献性质的,那么我们用猫树来代替st表即可达成 \(O(n\log \log n)\) 预处理 \(O(1)\) 查询满足结合律的东西。

不过现在这个版本的常数巨大与猫树没有区别,之后会重构一个版本。

代码:

#include<bits/stdc++.h>
using namespace std;
const int MX = 1e6 + 7; 
#define lc x << 1
#define rc x << 1 | 1
struct node{
	int l,r,mid;
	vector<int > pre,suf;
};
int pw[MX],lg2[MX];
int read(){
	int x = 0,ch = getchar();
	while(ch < 48 || ch > 57)ch = getchar();
	while(ch > 47 && ch < 58)x = (x << 3) + (x << 1) + ch - 48,ch = getchar();
	return x;
}
void init(int n){
	pw[0] = 1;
	for(int i = 1;i <= 30;i++){pw[i] = pw[i - 1] << 1;if(pw[i] <= (n << 3))lg2[pw[i]] = i;}
	for(int i = 1;i <= n << 3;i++)
		if(!lg2[i])lg2[i] = lg2[i - 1];
}
int lcp(int x,int y){
	return x >> (lg2[x ^ y] + 1);
}
const int B = 64;
struct tree{
	vector<int > a,id;
	vector<node > s;
	int sz,ty;
	void init(int n){
		if(pw[lg2[n]] != n)sz = pw[lg2[n] + 1];
		else sz = n;
		a.resize(sz + 5);
		id.resize(sz + 5);
		s.resize((sz << 2) + 5);
	}
	void set(int id,int x){
		a[id] = x;
	}
	void setall(vector<int > b){
		for(int i = 1;i <= sz;i++)a[i] = b[i];
	}
	void build(int x,int l,int r){
		int mid = l + r >> 1;
		s[x].l = l;s[x].r = r;
		s[x].mid = mid;
		if(ty == 1 || r - l + 1 <= B){
			s[x].pre.resize(mid - l + 5,0);
			s[x].suf.resize(r - mid + 5,0);
			for(int i = mid,p = mid - l + 1;i >= l;i--,p--)s[x].pre[p] = max(s[x].pre[p + 1],a[i]);
			for(int i = mid + 1,p = 1;i <= r;i++,p++)s[x].suf[p] = max(s[x].suf[p - 1],a[i]);
		}
		if(l == r){
			id[l] = x;
			return;
		}
		build(lc,l,mid);
		build(rc,mid + 1,r);
	}
	void rbuild(){build(1,1,sz);}
	int query(int l,int r){
		int lca = lcp(id[l],id[r]);
		return max(s[lca].pre[l - s[lca].l + 1],s[lca].suf[r - s[lca].mid]);
	}
};
struct rmq{
	vector<int > st,block;
	vector<int > id,id2;
	tree s1,s2;//s1表示整块,s2表示散块 
	void build(int n,vector<int > b){
		s1.ty = 1;s2.ty = 2;
		if(pw[lg2[n]] != n)n = pw[lg2[n] + 1];
		else n = n;
		st.resize(n + 5);id.resize(n + 5);id2.resize(n);
		block.resize(n / B + 5);
		for(int i = 1;i <= n;i++)st[i] = b[i];
		for(int l = 1,p = 1;l <= n;l += B,p++){
			int r = l + B - 1,maxn = 0;
			id2[l] = p;
			for(int j = l;j <= r;j++){
				id[j] = l;
				maxn = max(maxn,b[j]);
			}
			block[p] = maxn;
		}
		s1.init(n / B);s2.init(n);
		s1.setall(block);s2.setall(st);
		s1.rbuild();s2.rbuild();
	}
	int query(int l,int r){
        int ll = id[l],rr = id[r];
        int ret = 0;
        if(ll != rr){
            ret = max(ret,s2.query(l,ll + B - 1));
            if(id2[ll + B] <= id2[rr - B])ret = max(ret,s1.query(id2[ll + B],id2[rr - B]));
			ret = max(ret,s2.query(rr,r));
        }
        else ret = max(ret,s2.query(l,r));
        return ret;
    }
}rmq;
int main(){
	int n,q;
	n = read();q = read();
	init(n);
	vector<int > a;
	a.resize(n + 5,0);
	for(int i = 1;i <= n;i++)a[i] = read();
	if(n <= 64)n = 64;
	a.resize(n + 5,0);
	rmq.build(n,a);
	for(int i = 1;i <= q;i++){
		int l,r;
		l = read();r = read();
		cout << rmq.query(l,r) << '\n';
	}
	return 0;
}
posted @ 2023-10-31 07:53  _hjy  阅读(30)  评论(0)    收藏  举报