2018 Multi-University Training Contest 5--HDU 6356 Glad You Came

題意:

給你一個函數,用它求出長度爲3*m的數組,a數組一開始全爲0,有m個操作:l, r, v都可以用公式算出來,[l, r]區間內把所有小於v的a[i]替換成v。求出 [1,n]區間內的所有 (i*a[i]) 的異或和。

題解:

利用線段樹記錄區間的最大值和最小值,每次修改和查詢維護一下。如果最大值小於v就往下更新

剪枝:如果區間內的最小值大於v就不用走了,直接回去。

最後求出異或和。

#include <algorithm>
#include  <iostream>
#include   <cstdlib>
#include   <cstring>
#include    <cstdio>
#include    <string>
#include    <vector>
#include    <bitset>
#include     <stack>
#include     <cmath>
#include     <deque>
#include     <queue>
#include      <list>
#include       <set>
#include       <map>
#define mem(a) memset(a, 0, sizeof(a))
#define mid (tree[root].l+tree[root].r)/2
using namespace std;
typedef long long ll;
typedef unsigned int ui;

const int maxn = 1e5+10;
const int maxm = 5e6+10;
const int mod = 1 << 30;
struct Tree{
	int l, r, minn, maxx, lazy;
}tree[maxn << 2];
int n, m;
ui x, y, z, w, f[maxm*3], a[maxn];

void build_tree(int l, int r, int root){
	tree[root].l = l;
	tree[root].r = r;
	tree[root].minn = 0;
	tree[root].maxx = 0;
	tree[root].lazy = 0;
	//cout<<l<<" "<<mid<<" "<<r<<endl;
	if(r == l){
		return;
	}
	build_tree(l, mid, root << 1);
	build_tree(mid+1, r, (root << 1) | 1);
}

void push_up(int root){
	tree[root].minn = min(tree[root << 1].minn, tree[(root << 1) | 1].minn);
	tree[root].maxx = max(tree[root << 1].maxx, tree[(root << 1) | 1].maxx);
}

void push_down(int root){
	if(tree[root].lazy){
		tree[root << 1].lazy = tree[root].lazy;
		tree[(root << 1) | 1].lazy = tree[root].lazy;
		tree[root << 1].minn = tree[root].lazy;
		tree[(root << 1) | 1].minn = tree[root].lazy;
		tree[root << 1].maxx = tree[root].lazy;
		tree[(root << 1) | 1].maxx = tree[root].lazy;
		tree[root].lazy = 0;
	}
}

void update_tree(int l, int r, int root, ui v){
	if(tree[root].minn >= v){
		return;
	}
	if(l <= tree[root].l && r >= tree[root].r){
		if(tree[root].maxx < v){
			tree[root].maxx = v;
			tree[root].minn = v;
			tree[root].lazy = v;
			return;
		}
	}
	push_down(root);
	if(r <= mid){
		update_tree(l, r, root << 1, v);
	}
	else if(l >= mid+1){
		update_tree(l, r, (root << 1) | 1, v);
	}
	else{
		update_tree(l, mid, root << 1, v);
		update_tree(mid+1, r, (root << 1) | 1, v);
	}
	push_up(root);
}

void query_tree(int l, int r, int root){
	if(tree[root].maxx == tree[root].minn){
		for(int i = l; i <= r; i++){
			a[i] = tree[root].maxx;
		}
		return;
	}
	push_down(root);
	if(r <= mid){
		query_tree(l, r, root << 1);
	}
	else if(l >= mid+1){
		query_tree(l, r, (root << 1) | 1);
	}
	else{
		query_tree(l, mid, root << 1);
		query_tree(mid+1, r, (root << 1) | 1);
	}
}

ui RNG61(){
	x = x ^ (x << 11);
	x = x ^ (x >> 4);
	x = x ^ (x << 5);
	x = x ^ (x >> 14);
	w = x ^ (y ^ z);
	x = y;
	y = z;
	z = w;
	
	return z;
}

int main(){
	int t;
	scanf("%d", &t);
	while(t--){
		scanf("%d %d %u %u %u", &n, &m, &x, &y, &z);
		for(int i = 1; i <= m * 3; i++){
			f[i] = RNG61();
		}
		build_tree(1, n, 1);
		ui l, r, v;
		for(int i = 1; i <= m; i++){
			ui temp1 = f[i*3-2] % n + 1;
			ui temp2 = f[i*3-1] % n + 1;
			l = min(temp1, temp2);
			r = max(temp1, temp2);
			v = f[i*3] % mod;
			update_tree(l, r, 1, v);
		}
		ll ans = 0;
		query_tree(1, n, 1);
		for(int i = 1; i <= n; i++){
			ans ^= ((ll)i * (ll)a[i]);
		}
		printf("%lld\n", ans);
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章