[codeforces534E]Listening to Music && 可持久化线段树

每个线段树节点需要保存四个值,ls,rs,min,tag

由于空间不够 所以把他们压缩成一个unsinged long long

t[x] = (ls * N + rs) * T + val + tag

t[x] % T 即可得到val + tag, ls = t[x] / T / N, rs = t[x] / T % N

进行标记永久化过后可以用左右儿子的值解出自己的val,再解出tag

然后就卡着内存过去了

黑科技简直可怕

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<queue>
#define SF scanf
#define PF printf
#define mp make_pair
#define fir first
#define sec second
#define sqr(x) ((x)*(x))
using namespace std;
typedef long long LL;
typedef pair<int, int> pii;
typedef unsigned long long ull;
const int MAXN = 200000;
int n, m, rt[MAXN+10], Q;
pii a[MAXN+10];
struct Seg_Tree {
	static const int N = 8000000 + 10;
	static const int T = MAXN + 3;
	int ncnt;
	ull t[N];
	inline void calc_s(const bool &nl, const bool &nr, ull x, int &ls, int &rs, int &tag) {
		int s = x % T;
		ls = x / T / N; rs = x / T % N;
		tag = s - min((nl ? ls : t[ls] % T), (nr ? rs : t[rs] % T));
	}
	inline ull calc(const int &ls, const int &rs, const int &val) {
		return (1ull * ls * N + rs) * T + val;
	}
	void ins(const int &last, int &u, const int &L, const int &R, const int &l, const int &r) {
		if(L == R) {
			u = last+1;
			return ;
		}
		t[u = ++ncnt] = t[last];
		if(l <= L && R <= r) {
			t[u]++;
			return ;
		}
		int mid = (L+R) >> 1, ls, rs, val, lson = 0, rson = 0;
		calc_s((L == mid), (R == mid+1), t[u], ls, rs, val);
		if(l <= mid) ins(ls, lson, L, mid, l, r);
		if(r > mid) ins(rs, rson, mid+1, R, l, r);
		if(!lson) lson = ls;
		if(!rson) rson = rs;
		val += min(((L == mid) ? lson : t[lson] % T), ((R == mid+1) ? rson : t[rson] % T));
		t[u] = calc(lson, rson, val);
	}
	int query(const int &u, const int &L, const int &R, const int &l, const int &r) {
		if(L == R) return u;
		if(!u) return 0;
		if(l <= L && R <= r) return t[u] % T;
		int mid = (L+R) >> 1, ls, rs, val, ret = N;
		calc_s((L == mid), (mid+1 == R), t[u], ls, rs, val);
		if(l <= mid) ret = min(ret, query(ls, L, mid, l, r));
		if(r > mid) ret = min(ret, query(rs, mid+1, R, l, r));
		return ret + val;
	}
	inline void build() {
		for(int i = 1; i <= n; i++) 
			ins(rt[i-1], rt[i], 1, n-m+1, max(1, a[i].sec-m+1), a[i].sec);
	}
} seg;
int main() {
	SF("%d%d", &n, &m);
	for(int i = 1; i <= n; i++) SF("%d", &a[i].fir), a[i].sec = i;
	sort(a+1, a+1+n);
	seg.build();
	SF("%d", &Q);
	int ans = 0;
	for(int i = 1; i <= Q; i++) {
		int x, l, r;
		SF("%d%d%d", &l, &r, &x);
		x ^= ans;
		x = lower_bound(a+1, a+1+n, mp(x, 0)) - a;
		if(x == 1) ans = 0;
		else ans = seg.query(rt[x-1], 1, n-m+1, l, r);
		PF("%d\n", ans);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值