luogu P3793 由乃救爷爷

区间RMQ
所以为什么笛卡尔树可以*过去?
随便写一发就过了
可能是笛卡尔树期望常数比较小吧
code:

#include<bits/stdc++.h>
#define N 20000005
using namespace std;
namespace GenHelper
{
    unsigned z1,z2,z3,z4,b;
    unsigned rand_()
    {
    b=((z1<<6)^z1)>>13;
    z1=((z1&4294967294U)<<18)^b;
    b=((z2<<2)^z2)>>27;
    z2=((z2&4294967288U)<<2)^b;
    b=((z3<<13)^z3)>>21;
    z3=((z3&4294967280U)<<7)^b;
    b=((z4<<3)^z4)>>12;
    z4=((z4&4294967168U)<<13)^b;
    return (z1^z2^z3^z4);
    }
}
void srand(unsigned x)
{using namespace GenHelper;
z1=x; z2=(~x)^0x233333333U; z3=x^0x1234598766U; z4=(~x)+51;}
int read()
{
    using namespace GenHelper;
    int a=rand_()&32767;
    int b=rand_()&32767;
    return a*32768+b;
}// 上面是随机数生成
int n, m, s, a[N], sta[N], ls[N], rs[N];
int query(int l, int r) {
	int x = sta[1];
	for(; ;) {
		if(l <= x && x <= r) return a[x];
		if(x < r) x = rs[x];
		else x = ls[x];
	}
}
int main() {
	scanf("%d%d%d", &n, &m, &s);
	srand(s);
	for(int i = 1; i <= n; i ++) a[i] = read();
	int top = 0;
	for(int i = 1; i <= n; i ++) {
		int j = 0;
		while(top && a[sta[top]] <= a[i]) 
			j = sta[top --];
		ls[i] = j;
		if(top) rs[sta[top]] = i;
		sta[++ top] = i;
	}
	unsigned long long ans = 0;
	while(m --) {
		int l, r;
		l = read() % n + 1, r = read() % n + 1;
		if(l > r) swap(l, r);
		ans += query(l, r);	
	}
	printf("%llu", ans);
	return 0;
}
posted @ 2021-04-06 21:53  lahlah  阅读(24)  评论(0编辑  收藏  举报