【BZOJ2653】【主席树+二分】middle
Description
一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整。
给你一个长度为n的序列s。
回答Q个这样的询问:s的左端点在[a,b]之间,右端点在[c,d]之间的子序列中,最大的中位数。
其中a<b<c<d。
位置也从0开始标号。
我会使用一些方式强制你在线。
Input
第一行序列长度n。
接下来n行按顺序给出a中的数。
接下来一行Q。
然后Q行每行a,b,c,d,我们令上个询问的答案是x(如果这是第一个询问则x=0)。
令数组q={(a+x)%n,(b+x)%n,(c+x)%n,(d+x)%n}。
将q从小到大排序之后,令真正的要询问的a=q[0],b=q[1],c=q[2],d=q[3]。
输入保证满足条件。
Output
Q行依次给出询问的答案。
Sample Input
5
170337785
271451044
22430280
969056313
206452321
3
3 1 0 2
2 3 1 4
3 1 4 0
271451044
271451044
969056313
Sample Output
Hint
0:n,Q<=100
1,...,5:n<=2000
0,...,19:n<=20000,Q<=25000
Source
【分析】
居然wa了一下TAT.
比较简单的题目,按照权值大小初始化一下线段树将其可持久化,对于二分的版本求前缀和的最大最小值减一下看是否大于等于0就可以了。
1 /* 2 唐代贾岛 3 《剑客 / 述剑》 4 十年磨一剑,霜刃未曾试。 5 今日把示君,谁有不平事? 6 */ 7 #include <iostream> 8 #include <cstdio> 9 #include <algorithm> 10 #include <cstring> 11 #include <vector> 12 #include <utility> 13 #include <iomanip> 14 #include <string> 15 #include <cmath> 16 #include <queue> 17 #include <assert.h> 18 #include <map> 19 #include <ctime> 20 #include <cstdlib> 21 #include <stack> 22 #define LOCAL 23 const int INF = 0x7fffffff; 24 const int MAXN = 20000 + 10; 25 const int maxnode = 20000 * 2 + 200000 * 20; 26 const int maxm= 30000 * 2 + 10; 27 using namespace std; 28 struct DATA{ 29 int num; 30 int order; 31 bool operator < (const DATA &b)const{ 32 return num < b.num; 33 } 34 }sorted[MAXN]; 35 int data[MAXN]; 36 struct Node{ 37 int l, r; 38 int Max, val, sum, Min; 39 Node *ch[2]; 40 }*root[MAXN], mem[maxnode]; 41 int tot, n; 42 43 Node *NEW(int l, int r){ 44 Node *p = &mem[tot++]; 45 p->l = l; 46 p->r = r; 47 p->val = p->sum = p->Max = p->Min = 1; 48 p->ch[0] = p->ch[1] = NULL; 49 return p; 50 } 51 void update(Node *&t){ 52 if (t->l == t->r) return; 53 t->sum = 0; 54 if (t->ch[0] != NULL) t->sum += t->ch[0]->sum; 55 if (t->ch[1] != NULL) t->sum += t->ch[1]->sum; 56 57 t->Max = max(t->ch[1]->Max + t->ch[0]->sum, t->ch[0]->Max); 58 t->Min = min(t->ch[1]->Min + t->ch[0]->sum, t->ch[0]->Min); 59 return; 60 } 61 void build(Node *&t, int l, int r){ 62 if (t == NULL){ 63 t = NEW(l, r); 64 } 65 if (l == r) return; 66 int mid = (l + r) >> 1; 67 build(t->ch[0], l, mid); 68 build(t->ch[1], mid + 1, r); 69 update(t); 70 } 71 //将l改为-1 72 void change(Node *&t, Node *&last, int l){ 73 if (t == NULL){ 74 t = NEW(last->l, last->r); 75 t->val = last->val; 76 t->Max = last->Max; 77 t->Min = last->Min; 78 t->sum = last->sum; 79 } 80 if (t->l == l && t->r == l){ 81 t->Min = t->Max = t->sum = -1; 82 return; 83 } 84 int mid = (t->l + t->r) >> 1; 85 if (l <= mid){ 86 change(t->ch[0], last->ch[0], l); 87 t->ch[1] = last->ch[1]; 88 }else{ 89 change(t->ch[1], last->ch[1], l); 90 t->ch[0] = last->ch[0]; 91 } 92 update(t); 93 } 94 int qSum(Node *t, int l, int r){ 95 if (l > r) return 0; 96 if (l == 0) return qSum(t, l + 1, r); 97 98 if (l <= t->l && t->r <= r) return t->sum; 99 int mid = (t->l + t->r) >>1; 100 int sum = 0; 101 if (l <= mid) sum += qSum(t->ch[0], l, r); 102 if (r > mid) sum += qSum(t->ch[1], l, r); 103 return sum; 104 } 105 int qMax(Node *t, int l, int r, int k){ 106 if (l == 0) return max(0, qMax(t, l + 1, r, k)); 107 108 if (l <= t->l && t->r <= r) return t->Max + qSum(root[k], 1, t->l - 1); 109 int mid = (t->l + t->r) >> 1; 110 int Ans = -INF; 111 if (l <= mid) Ans = max(Ans, qMax(t->ch[0], l, r, k)); 112 if (r > mid) Ans = max(Ans, qMax(t->ch[1], l, r, k)); 113 return Ans; 114 } 115 int qMin(Node *t, int l, int r, int k){ 116 if (l == 0) return min(0, qMin(t, l + 1, r, k)); 117 118 if (l <= t->l && t->r <= r) return t->Min + qSum(root[k], 1, t->l - 1); 119 int mid = (t->l + t->r) >> 1; 120 int Ans = INF; 121 if (l <= mid) Ans = min(Ans, qMin(t->ch[0], l, r, k)); 122 if (r > mid) Ans = min(Ans, qMin(t->ch[1], l, r, k)); 123 return Ans; 124 } 125 126 void init(){ 127 scanf("%d", &n); 128 for (int i = 1; i <= n; i++){ 129 sorted[i].order = i; 130 scanf("%d", &sorted[i].num); 131 data[i] = sorted[i].num; 132 } 133 //离散化 134 sort(sorted + 1, sorted + 1 + n); 135 136 tot = 0; 137 root[1] = NULL; 138 build(root[1], 1, n); 139 //开始可持久化 140 for (int i = 2; i <= (n + 1); i++) change(root[i], root[i - 1], sorted[i - 1].order); 141 //printf("%d", root[6]->Max); 142 /*int cnt = 0; 143 for (int i = 1; i <= n; i++){ 144 if (i == 0 || sorted[i].num != sorted[i - 1].num) cnt++; 145 rem[cnt] = sorted[i].num; 146 data[sorted[i].order] = cnt; 147 }*/ 148 //for (int i = 1; i <= n; i++) 149 } 150 int search(int a, int b, int c, int d){ 151 int Ans, l = 1, r = n; 152 while (l <= r){ 153 int mid = (l + r) >> 1; 154 if ((qMax(root[mid], c, d, mid) - qMin(root[mid], a, b, mid)) >= 0) Ans = mid, l = mid + 1; 155 else r = mid - 1; 156 } 157 return Ans; 158 } 159 void work(){ 160 int last_ans = 0, m; 161 scanf("%d", &m); 162 for (int i = 1; i <= m; i++){ 163 int q[5]; 164 for (int j = 1; j <= 4; j++){ 165 scanf("%d", &q[j]); 166 q[j] = (q[j] + last_ans) % n; 167 } 168 sort(q + 1, q + 1 + 4); 169 int a = q[1], b = q[2], c = q[3], d = q[4]; 170 a++;c++; 171 b++;d++; 172 //printf("%d", qMax(root[5], 3, 3, 5)); 173 //printf("%d%d%d%d\n", a, b, c, d); 174 last_ans = sorted[search(a - 1, b - 1, c, d)].num; 175 printf("%d\n", last_ans); 176 } 177 } 178 179 int main (){ 180 181 init(); 182 work(); 183 return 0; 184 }