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;
    }
  • 相关阅读:
    React 进修之路(1)
    requireJS的配置心得
    DOM的内部插入和外部插入
    h5移动端设备像素比dpr介绍
    原生js--事件类型
    React 进修之路(3)
    javaScript
    html&css
    MyBatis
    Maven基础
  • 原文地址:https://www.cnblogs.com/zeolim/p/12270341.html
Copyright © 2011-2022 走看看