码迷,mamicode.com
首页 > 其他好文 > 详细

HDU-6356 Glad You Came 线段树+剪枝

时间:2021-02-15 12:15:44      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:统计   signed   cpp   min   query   朴素   struct   target   sign   

\(\text{原题链接}\)

\(\text{题目大意}\)

初始有一个长度为 \(n\) 的序列 \(a\),初始全 \(0\)

\(m\) 次修改,每次修改 \((l,r,v)\),让 \(a_i = \max(a_i, v), (l\leq i\leq r)\)。求出所有操作后的 \(\bigoplus_{i = 1}^{n}{(i \cdot a_i)}\)

其中这 \(m\) 次修改的生成方式为:

给定初始的\(32\)位非负整数 \(X,Y,Z\)

技术图片

调用 \(3m\) 次上图中的 \(RNG61()\),记结果为 \(f_1,f_2,f_3...f_3m\)。其中第 \(i\) 次修改的 \(l_i,r_i,v_i\) 为:

\[\begin{cases} l_i &= \min\left((f_{3 i - 2} \bmod n) + 1, (f_{3 i - 1} \bmod n) + 1\right) \\ r_i &= \max\left((f_{3 i - 2} \bmod n) + 1, (f_{3 i - 1} \bmod n) + 1\right) \\ v_i &= f_{3 i} \bmod 2^{30}\end{cases} (i = 1, 2, \cdots, m) \]

\(T\) 组数据,每次给定 \(n,m,X,Y,Z\)

\(1 \leq T \leq 100\),\(1 \leq n \leq 10^5\),\(1 \leq m \leq 5 \cdot 10^6\),\(0 \leq X, Y, Z < 2^{30}\)

\(\mathcal{Solution}\)

其实就是区间取 \(max\),最后需要给出整个序列,朴素的线段树过不了,由于修改的 \(l,r,v\) 在一定程度上是随机的,所以考虑剪枝优化。

第一种方法:标记永久化,维护一下每个区间的永久标记,最后在线段树上跑一边 dfs 统计结果(抄自oi-wiki)。剪枝优化:如果当前区间的永久标记已经 \(\geq\) 当前修改的值,直接返回,不继续向下修改。

第二种方法:维护区间最小值,这个就不用标记永久化了。剪枝优化:如果当前区间的最小值已经 \(\geq\) 当前修改的值,直接返回,不继续向下修改。

\(\mathcal{Code}\)

第一种方法:

#include<iostream>
#include<cstdio>
#include<algorithm>
namespace do_while_true {
	#define ld double
	#define ll long long
	#define ui unsigned int
	#define re register
	#define pb push_back
	#define fir first
	#define sec second
	#define pp std::pair
	#define mp std::make_pair
	const ll mod = 998244353;
	template <typename T>
	inline T Max(T x, T y) { return x > y ? x : y; }
	template <typename T>
	inline T Min(T x, T y) { return x < y ? x : y; }
	template <typename T>
	inline T Abs(T x) {	return x < 0 ? -x : x; }
	template <typename T>
	inline T& read(T& r) {
		r = 0; bool w = 0; char ch = getchar();
		while(ch < ‘0‘ || ch > ‘9‘) w = ch == ‘-‘ ? 1 : 0, ch = getchar();
		while(ch >= ‘0‘ && ch <= ‘9‘) r = r * 10 + (ch ^ 48), ch = getchar();
		return r = w ? -r : r;
	}
	template <typename T>
	inline T qpow(T x, T y) {
		re T sumq = 1; x %= mod;
		while(y) {
			if(y&1) sumq = sumq * x % mod;
			x = x * x % mod;
			y >>= 1;
		}
		return sumq;
	}
	char outch[110];
	int outct;
	template <typename T>
	inline void print(T x) {
		do {
			outch[++outct] = x % 10 + ‘0‘;
			x /= 10;
		} while(x);
		while(outct >= 1) putchar(outch[outct--]);
	}
}
using namespace do_while_true;

const int N = 100010;
const int M = 5000100; 

int n, m, a[N];
ui f[M*3];
#define ls tree[x].lson
#define rs tree[x].rson
int trnt = 1;
struct SGT {
	int l, r, lson, rson, tag;
}tree[N<<1];

void build(int x, int l, int r) {
	tree[x].l = l; tree[x].r = r; tree[x].tag = 0;
	if(l == r) return ;
	ls = ++trnt; rs = ++trnt;
	build(ls, l, (l+r)>>1); build(rs, tree[ls].r+1, r);
}
void modify(int x, int l, int r, int v) {
	if(tree[x].tag >= v) return ;
	if(tree[x].l >= l && tree[x].r <= r) {
		tree[x].tag = Max(tree[x].tag, v);
		return ;
	}
	int mid = (tree[x].l + tree[x].r) >> 1;
	if(mid >= l) modify(ls, l, r, v);
	if(mid < r) modify(rs, l, r, v);
}
void query(int x, int mx) {
	mx = Max(tree[x].tag, mx);
	if(tree[x].l == tree[x].r) {
		a[tree[x].l] = mx;
		return ;
	}
	query(ls, mx); query(rs, mx);
}

#undef ls
#undef rs 

void solve() {
	read(n); read(m);
	trnt = 1; build(1, 1, n);
	ui x, y, z; read(x); read(y); read(z);
	for(int i = 1; i <= 3 * m; ++i) { x = x ^ (x << 11),x = x ^ (x >> 4),x = x ^ (x << 5),x = x ^ (x >> 14);ui w = x ^ (y ^ z);x = y,y = z,z = w,f[i] = z;}
	for(int i = 1, l, r, v; i <= m; ++i) {
		l = Min(f[3*i-2] % n + 1, f[3*i-1] % n + 1);
		r = Max(f[3*i-2] % n + 1, f[3*i-1] % n + 1);
		v = f[3*i] % (1 << 30);
		modify(1, l, r, v); 
	}
	query(1, 0); ll ans = 0;
	for(int i = 1; i <= n; ++i)
		ans ^= 1ll * i * a[i];
	printf("%lld\n", ans);
}

signed main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	#endif
	int T = 1;
	read(T);
	while(T--) solve();
	fclose(stdin);
	return 0;
}

第二种方法:

#include<iostream>
#include<cstdio>
#include<algorithm>
namespace do_while_true {
	#define ld double
	#define ll long long
	#define ui unsigned int
	#define re register
	#define pb push_back
	#define fir first
	#define sec second
	#define pp std::pair
	#define mp std::make_pair
	const ll mod = 998244353;
	template <typename T>
	inline T Max(T x, T y) { return x > y ? x : y; }
	template <typename T>
	inline T Min(T x, T y) { return x < y ? x : y; }
	template <typename T>
	inline T Abs(T x) {	return x < 0 ? -x : x; }
	template <typename T>
	inline T& read(T& r) {
		r = 0; bool w = 0; char ch = getchar();
		while(ch < ‘0‘ || ch > ‘9‘) w = ch == ‘-‘ ? 1 : 0, ch = getchar();
		while(ch >= ‘0‘ && ch <= ‘9‘) r = r * 10 + (ch ^ 48), ch = getchar();
		return r = w ? -r : r;
	}
	template <typename T>
	inline T qpow(T x, T y) {
		re T sumq = 1; x %= mod;
		while(y) {
			if(y&1) sumq = sumq * x % mod;
			x = x * x % mod;
			y >>= 1;
		}
		return sumq;
	}
	char outch[110];
	int outct;
	template <typename T>
	inline void print(T x) {
		do {
			outch[++outct] = x % 10 + ‘0‘;
			x /= 10;
		} while(x);
		while(outct >= 1) putchar(outch[outct--]);
	}
}
using namespace do_while_true;

const int N = 100010;
const int M = 5000100; 

int n, m, a[N];
ui f[M*3];
#define ls tree[x].lson
#define rs tree[x].rson
int trnt = 1;
struct SGT {
	int l, r, lson, rson, mn, tag;
}tree[N<<1];

inline void pushup(int x) { tree[x].mn = Min(tree[ls].mn, tree[rs].mn); } 
inline void pushdown(int x) {
	if(tree[x].tag) {
		int p = tree[x].tag; tree[x].tag = 0;
		tree[ls].tag = Max(tree[ls].tag, p); tree[rs].tag = Max(tree[rs].tag, p);
		tree[ls].mn = Max(tree[ls].mn, p);
		tree[rs].mn = Max(tree[rs].mn, p);
	}
}

void build(int x, int l, int r) {
	tree[x].l = l; tree[x].r = r; tree[x].tag = 0; tree[x].mn = 0;
	if(l == r) return ;
	ls = ++trnt; rs = ++trnt;
	build(ls, l, (l+r)>>1); build(rs, tree[ls].r+1, r);
}
void modify(int x, int l, int r, int v) {
	if(tree[x].mn >= v) return ;
	if(tree[x].l >= l && tree[x].r <= r) {
		tree[x].mn = Max(tree[x].mn, v); 
		tree[x].tag = Max(tree[x].tag, v);
		return ;
	}
	pushdown(x);
	int mid = (tree[x].l + tree[x].r) >> 1;
	if(mid >= l) modify(ls, l, r, v);
	if(mid < r) modify(rs, l, r, v);
	pushup(x);
}
void query(int x) {
	if(tree[x].l == tree[x].r) {
		a[tree[x].l] = tree[x].mn;
		return ;
	}
	pushdown(x);
	query(ls); query(rs);
}

#undef ls
#undef rs 

void solve() {
	read(n); read(m);
	trnt = 1; build(1, 1, n);
	ui x, y, z; read(x); read(y); read(z);
	for(int i = 1; i <= 3 * m; ++i) { x = x ^ (x << 11),x = x ^ (x >> 4),x = x ^ (x << 5),x = x ^ (x >> 14);ui w = x ^ (y ^ z);x = y,y = z,z = w,f[i] = z;}
	for(int i = 1, l, r, v; i <= m; ++i) {
		l = Min(f[3*i-2] % n + 1, f[3*i-1] % n + 1);
		r = Max(f[3*i-2] % n + 1, f[3*i-1] % n + 1);
		v = f[3*i] % (1 << 30);
		modify(1, l, r, v); 
	}
	query(1); ll ans = 0;
	for(int i = 1; i <= n; ++i)
		ans ^= 1ll * i * a[i];
	printf("%lld\n", ans);
}

signed main() {
	#ifndef ONLINE_JUDGE
	freopen("in.txt", "r", stdin);
	#endif
	int T = 1;
	read(T);
	while(T--) solve();
	fclose(stdin);
	return 0;
}

HDU-6356 Glad You Came 线段树+剪枝

标签:统计   signed   cpp   min   query   朴素   struct   target   sign   

原文地址:https://www.cnblogs.com/do-while-true/p/14397600.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!