[可持久化权值线段树] hdu 6703 array

题意:

给定一个1-n的排列,两种操作

1. (1,pos),indicating to change the value of apos to apos+10,000,000;
2. (2,r,k),indicating to ask the minimum value which is **not equal** to any ai ( 1≤i≤r ) and **not less ** than k.

查找不等于a[1] - a[r]间任何元素的且大于等于k的最小值


解题思路:

k数据范围为1e5 操作1加了1e7

所以2操作的最大答案就是n + 1,因为1-n排列的任意值+1e7都完全大于n + 1

这样考虑,如果一个数字+1e7了,说明这个值已经不在这个排列之中了,所以可以直接使用作为答案

那么问题分解为查找一个最接近k的元素不等于1-r之中任意元素或r + 1 到 n + 1之间任意元素

那么可以保存一个set记录不在排列中的值

用可持久线段树查r + 1 到 n + 1之中大于等于k的第一个元素(必然可以使用)

或已经+1e7的元素(必然可以使用即可)


代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXN = 1e5 + 100;
int root[MAXN], tot = 0;
struct node
{
	int ls, rs, val;
}t[MAXN << 5];

void update(int l, int r, int &now, int lst, int pos)
{
	now = ++tot;
	t[now] = t[lst];
	++t[now].val;
	if(l == r)	{ return ; }
	int mid = (l + r) >> 1;
	if(pos <= mid) update(l, mid, t[now].ls, t[lst].ls, pos);
	else update(mid + 1, r, t[now].rs, t[lst].rs, pos);
}

int fp = 0;

void find(int l, int r, int now, int pos)
{
	if(r < pos || l >= fp)
		return ;
	if(l == r)
	{
		fp = min(fp, l);
		return ;
	}
	int mid = (l + r) >> 1;
	
	if(pos <= mid && t[t[now].ls].val)
		find(l, mid, t[now].ls, pos);
	
	if(t[t[now].rs].val)
		find(mid + 1, r, t[now].rs, pos);
}

int arr[MAXN] = {0};

void init(int n)
{
	memset(root, 0, sizeof(root));
	tot = 0;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0); cout.tie(0); 
	
	int T, n, m;
	
	cin >> T;
	
	while(T--)
	{
		cin >> n >> m;
		
		for(int i = 1; i <= n; ++i)
			cin >> arr[i];
		
		init(n);
		
		update(1, n + 1, root[n + 1], root[n + 2], n + 1);
		
		set <int> ST;
		
		ST.insert(n + 1);
		
		for(int i = n; i >= 1; --i)
			update(1, n + 1, root[i], root[i + 1], arr[i]);
			
		int lans = 0;
		
		while(m--)
		{
			int opt, pos, t1, t2, t3, r, k;
			cin >> opt;
			
			if(opt == 1)
			{
				cin >>t1;
				t1 ^= lans;
				ST.insert(arr[t1] );
			} 
			else
			{
			 	cin >> t2 >> t3;
			 	
			 	t2 ^= lans; t3 ^= lans;
				
				//cout << t2 << ' ' << t3 << '
';
				
				fp = n + 1;
				find(1, n + 1, root[t2 + 1], t3);
				lans = min(fp, *ST.lower_bound(t3));
				cout << lans << '
';
			}
		}
	}
	
	return 0;
}
原文地址:https://www.cnblogs.com/zeolim/p/12270341.html