【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 }
View Code

 

你可能感兴趣的:(DDL)