Uva 12299 带循环移动的RMQ(线段树)

Posted 树的种子

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Uva 12299 带循环移动的RMQ(线段树)相关的知识,希望对你有一定的参考价值。

题目链接:https://vjudge.net/contest/147973#problem/C

题意:传统的RMQ是一个不变的数组a求区间最值。现在要循环移动(往前移动)。

分析:求区间问题,很容易想到线段树,西东就相当于单点更新。

建树,有两种方案,第一种是nlogn,就是不断的更新,更新logn,有n个数。

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 
 6 const int INF = 1000000000;
 7 const int maxnode = 1<<18;
 8 
 9 int op, qL, qR, p, v;   //qL,qR询问区间,p修改点,v修改值
10 
11 struct IntervalTree
12 {
13     int minv[maxnode];
14 
15     //修改:A[p] = v;
16     void update (int o,int L,int R)
17     {
18         int M = L + (R-L)/2;
19         if(L==R) minv[o] = v;
20         else
21         {
22             if(p<=M) update(o*2,L,M);
23             else update(o*2+1,M+1,R);
24             minv[o] = min(minv[o*2],minv[o*2+1]);
25         }
26     }
27 
28     //询问[ql,qr]中的最小值
29     int query(int o,int L,int R)
30     {
31         int M = L+(R-L)/2,ans = INF;
32         if(qL<=L&&R<=qR) return minv[o];
33         if(qL<=M) ans = min(ans,query(o*2,L,M));
34         if(M<qR) ans = min(ans,query(o*2+1,M+1,R));
35         return ans;
36     }
37 
38 };
39 
40 IntervalTree tree;
41 const int maxn = 100000 + 10;
42 int A[maxn];
43 
44 int main()
45 {
46     int n,q;
47     memset(&tree,0,sizeof(tree));
48 
49     scanf("%d%d",&n,&q);
50 
51     for(p=1; p<=n; p++)
52     {
53         scanf("%d",&v);
54         A[p] = v;
55         tree.update(1,1,n);
56     }
57 
58     int k,args[20],original[20];
59     char cmd[100];
60     while(q--)
61     {
62         scanf("%s", cmd);
63         int len = strlen(cmd);
64         k = 0;
65         args[k] = 0;
66         for(int i = 6; i < len; i++)
67         {
68             if(isdigit(cmd[i])) args[k] = args[k] * 10 + cmd[i] - 0;
69             else
70             {
71                 k++;
72                 args[k] = 0;
73             }
74         }
75         if(cmd[0] == q)
76         {
77             qL = args[0];
78             qR = args[1];
79             printf("%d\n", tree.query(1, 1, n));
80         }
81         else
82         {
83             for(int i = 0; i < k; i++) original[i] = A[args[i]];
84             for(int i = 0; i < k; i++)
85             {
86                 p = args[i];
87                 v = A[p] = original[(i+1)%k];
88                 tree.update(1, 1, n);
89             }
90         }
91     }
92     return 0;
93 }

 第二种是有一个build的过程,先将数组存起来,然后build,应用到要维护的信息上去。

  1 #include <bits/stdc++.h>
  2 
  3 using namespace std;
  4 
  5 
  6 const int INF = 1000000000;
  7 const int maxnode = 1<<18;
  8 
  9 const int maxn = 100000 + 10;
 10 int A[maxn];
 11 int op, qL, qR, p, v;
 12 
 13 struct IntervalTree
 14 {
 15     int minv[maxnode];
 16 
 17 
 18     void build(int o,int L,int R)
 19     {
 20         int M = L + (R-L)/2;
 21         if(L==R) minv[o] = A[L];
 22         else
 23         {
 24             build(o*2,L,M);
 25             build(o*2+1,M+1,R);
 26             minv[o] = min(minv[o*2],minv[o*2+1]);
 27         }
 28     }
 29 
 30     //点修改 d[p] =v;
 31     void update(int o,int L,int R)
 32     {
 33         int M = L + (R-L)/2;
 34         if(L==R) minv[o] = v;
 35         else
 36         {
 37             if(p<=M) update(o*2,L,M);
 38             else update(o*2+1,M+1,R);
 39             minv[o] = min(minv[o*2],minv[o*2+1]);
 40         }
 41     }
 42 
 43     int query(int o,int L,int R)
 44     {
 45 
 46         int M = L + (R-L)/2,ans=INF;
 47         if(qL<=L&&R<=qR)
 48             return minv[o];
 49 
 50         if(qL<=M) ans = min(ans,query(o*2,L,M));
 51         if(M<qR) ans = min(ans,query(o*2+1,M+1,R));
 52 
 53         return ans;
 54     }
 55 
 56 };
 57 
 58 IntervalTree tree;
 59 
 60 int main()
 61 {
 62     int n,q;
 63     scanf("%d%d",&n,&q);
 64     memset(&tree,0,sizeof(tree));
 65     for(int i=1; i<=n; i++)
 66         scanf("%d",&A[i]);
 67     tree.build(1,1,n);
 68 
 69     int k,args[20],original[20];
 70     char cmd[100];
 71     while(q--)
 72     {
 73         scanf("%s", cmd);
 74         int len = strlen(cmd);
 75         k = 0;
 76         args[k] = 0;
 77         for(int i = 6; i < len; i++)
 78         {
 79             if(isdigit(cmd[i])) args[k] = args[k] * 10 + cmd[i] - 0;
 80             else
 81             {
 82                 k++;
 83                 args[k] = 0;
 84             }
 85         }
 86         if(cmd[0] == q)
 87         {
 88             qL = args[0];
 89             qR = args[1];
 90             printf("%d\n", tree.query(1, 1, n));
 91         }
 92         else
 93         {
 94             for(int i = 0; i < k; i++) original[i] = A[args[i]];
 95             for(int i = 0; i < k; i++)
 96             {
 97                 p = args[i];
 98                 v = A[p] = original[(i+1)%k];
 99                 tree.update(1, 1, n);
100             }
101         }
102     }
103     return 0;
104 }

 

以上是关于Uva 12299 带循环移动的RMQ(线段树)的主要内容,如果未能解决你的问题,请参考以下文章

题解 UVA12299 RMQ with Shifts

UVa 12299 RMQ with Shifts(移位RMQ)

UVA 11235 Frequent values 线段树/RMQ

暑假集训day8

[UVa11235]Frequent values

线段树+RMQ问题第二弹