zoukankan      html  css  js  c++  java
  • [可持久化权值线段树] 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;
    }
  • 相关阅读:
    949. Largest Time for Given Digits
    450. Delete Node in a BST
    983. Minimum Cost For Tickets
    16. 3Sum Closest java solutions
    73. Set Matrix Zeroes java solutions
    347. Top K Frequent Elements java solutions
    215. Kth Largest Element in an Array java solutions
    75. Sort Colors java solutions
    38. Count and Say java solutions
    371. Sum of Two Integers java solutions
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270341.html
Copyright © 2011-2022 走看看