hdu 6703 array 权值线段树

题目读了半天没读懂......

给你一个长度为n的排列a。两种操作,每次把里面的某个数增加10,000,000,或者询问不等于a1-ar,且不小于k的最小的数是多少。k不超过n。所以答案必定不超过n+1。

我们考虑对原序列做权值线段树,下标为原序列的值,值为原序列的下标。

先考虑没有修改,那么不小于k就是只从线段树下标为[k + 1,n + 1]的范围找答案。不等于a1-ar就是线段树的值(原序列下标)要大于r。要最小的数,就是能往左子树找就往左子树找。

考虑修改,某个数ai增加了10,000,000,则意味着,原先ai这个数,再也不会被a1-ar这个条件限制了,因为a是一个排列,ai独此一份,现在被改成了个很大的数。所以干脆把线段树下标ai对应的值改成n+1,这样子,就再也不会受a1-ar这个条件限制了。

复杂度是mlogn,直观感受下就是,不再范围内的部分,发现出界会立马停止。在范围内的部分,只有一条会递归到底,一共两条,所是logn。

 1 #include <cstdio>
 2 #include <algorithm>
 3 #include <cstring>
 4 #include <cmath>
 5 using namespace std;
 6 const int MAXN = 101000;
 7 int n,m,T,vec[MAXN],a[MAXN];
 8 struct segtree
 9 {
10     int maxn[4 * MAXN]; 
11     void build(int k,int l,int r,int *vec)
12     {
13         if (l == r)
14         {
15             maxn[k] = vec[l];
16             return;
17         }
18         int mid = l + r >> 1;
19         build(k << 1,l,mid,vec);
20         build(k << 1 | 1,mid + 1,r,vec);
21         maxn[k] = max(maxn[k << 1],maxn[k << 1 | 1]);
22     }
23     void change(int k,int l,int r,int x)
24     {
25         if (l == r)
26         {
27             maxn[k] = n + 1;
28             return;
29         }
30         int mid = l + r >> 1;
31         if (x <= mid)
32             change(k << 1,l,mid,x);
33         else
34             change(k << 1 | 1,mid + 1,r,x);
35         maxn[k] = max(maxn[k << 1],maxn[k << 1 | 1]);
36     }
37     int query(int k,int l,int r,int x,int y)
38     {
39         if (r < y)
40             return -1;
41         if (l == r)
42             return l;
43         int mid = l + r >> 1,res = -1;
44         if (maxn[k << 1] > x)
45             res = query(k << 1,l,mid,x,y);
46         if (res == -1)
47             if (maxn[k << 1 | 1] > x)
48                 res = query(k << 1 | 1,mid + 1,r,x,y);
49         return res;
50     }
51 } st;
52 int main()
53 {
54     for (scanf("%d",&T);T != 0;T--)
55     {
56         
57         int lst = 0;
58         scanf("%d%d",&n,&m);
59         for (int i = 1;i <= n;i++)
60         {
61             scanf("%d",&a[i]);
62             vec[a[i]] = i;
63         }
64         vec[n + 1] = n + 1;
65         st.build(1,1,n + 1,vec);
66         int tx,ty,opt;
67         for (int i = 1;i <= m;i++)
68         {
69             scanf("%d",&opt);
70             if (opt == 1)
71             {
72                 scanf("%d",&tx);
73                 tx ^= lst;
74                 st.change(1,1,n + 1,a[tx]);
75             }else
76             {
77                 scanf("%d%d",&tx,&ty);
78                 tx ^= lst;
79                 ty ^= lst;
80                 lst = st.query(1,1,n + 1,tx,ty);
81                 printf("%d
",lst); 
82             }
83         }
84     }
85 }
心之所动 且就随缘去吧
原文地址:https://www.cnblogs.com/iat14/p/11404869.html