Advertisement
ec1117

Untitled

Jan 31st, 2021
121
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.49 KB | None | 0 0
  1. Bombs
  2.  
  3. Let's come up with some criteria that answer is <x.
  4.  
  5. We claim that the answer is <x if:
  6.  
  7. There is at least one bomb after the rightmost value ≥x.
  8. There are at least two bombs after the next rightmost value ≥x.
  9. ...
  10.  
  11. There are at least k bombs after the k-th rightmost value ≥x.
  12. Let ansi be the answer for bombs q1,q2,…,qi−1.
  13.  
  14. Then, ansi≥ansi+1.
  15.  
  16. Let's add new bombs starting from ansi−1, and while the actual answer is smaller than the current answer, decrease the actual answer.
  17.  
  18. To do this quickly, we'll use a segment tree.
  19.  
  20. In the segment tree, let's store bi= (number of values ≥x on suffix i…n) − (number of bombs on this suffix).
  21.  
  22. Then, the real answer is <x if bi≤0 for all i.
  23.  
  24. Using range addition updates and max queries, we can update b and decrease the answer quickly.
  25.  
  26. #include <bits/stdc++.h>
  27. using namespace std;
  28.  
  29. const int MX = 3e5 + 1;
  30.  
  31. int st[4 * MX], la[4 * MX], p[MX], q[MX], pos[MX], n;
  32.  
  33. void push(int v) {
  34. st[v * 2] += la[v];
  35. la[v * 2] += la[v];
  36. st[v * 2 + 1] += la[v];
  37. la[v * 2 + 1] += la[v];
  38. la[v] = 0;
  39. }
  40.  
  41. void upd(int a, int b, int val, int v = 1, int l = 1, int r = n) {
  42. if (b < l || r < a)
  43. return;
  44. if (a <= l && r <= b) {
  45. st[v] += val;
  46. la[v] += val;
  47. } else {
  48. push(v);
  49. int m = (l + r) / 2;
  50. upd(a, b, val, v * 2, l, m);
  51. upd(a, b, val, v * 2 + 1, m + 1, r);
  52. st[v] = max(st[v * 2], st[v * 2 + 1]);
  53. }
  54. }
  55.  
  56. int main() {
  57. ios_base::sync_with_stdio(0);
  58. cin.tie(0);
  59.  
  60. cin >> n;
  61. for (int i = 1; i <= n; ++i) {
  62. cin >> p[i];
  63. pos[p[i]] = i;
  64. }
  65. for (int i = 1; i <= n; ++i) {
  66. cin >> q[i];
  67. }
  68.  
  69. int cur = n;
  70. upd(1, pos[n], 1);
  71. for (int i = 1; i <= n; ++i) {
  72. cout << cur << ' ';
  73. upd(1, q[i], -1);
  74. while (cur && st[1] <= 0) {
  75. upd(1, pos[--cur], 1);
  76. }
  77. }
  78. cout << '\n';
  79. }
  80.  
  81.  
  82. /**
  83. * Description: 1D range update and query. Set SZ to a power of 2.
  84. * Source: USACO Counting Haybales
  85. * Verification: SPOJ Horrible
  86. */
  87.  
  88. template<class T, int SZ> struct LazySeg {
  89. T mx[2*SZ], lazy[2*SZ];
  90. LazySeg() { F0R(i,2*SZ) mx[i] = lazy[i] = 0; }
  91. void push(int ind, int L, int R) { /// modify values for current node
  92. if (L != R) F0R(i,2) lazy[2*ind+i] += lazy[ind]; /// prop to children
  93. mx[ind] += lazy[ind]; lazy[ind] = 0;
  94. } // recalc values for current node
  95. void pull(int ind) { mx[ind] = max(mx[2*ind],mx[2*ind+1]); }
  96. void build() { ROF(i,1,SZ) pull(i); }
  97. void upd(int lo,int hi,T inc,int ind=1,int L=0, int R=SZ-1) {
  98. push(ind,L,R); if (hi < L || R < lo) return;
  99. if (lo <= L && R <= hi) {
  100. lazy[ind] = inc; push(ind,L,R); return; }
  101. int M = (L+R)/2;
  102. upd(lo,hi,inc,2*ind,L,M); upd(lo,hi,inc,2*ind+1,M+1,R);
  103. pull(ind);
  104. }
  105. int firstGre(int ind = 1, int L = 0, int R = SZ-1) {
  106. push(ind,L,R); assert(mx[ind] > 0);
  107. if (L == R) return L;
  108. int M = (L+R)/2;
  109. push(2*ind,L,M);
  110. if (mx[2*ind] > 0) return firstGre(2*ind,L,M);
  111. return firstGre(2*ind+1,M+1,R);
  112. }
  113. };
  114. LazySeg<ll,1<<19> L;
  115.  
  116. /**
  117. * Description: 1D point update, range query where \texttt{comb} is
  118. * any associative operation. If $N$ is not power of 2 then
  119. * operations work but \texttt{seg[1] != query(0,N-1)}.
  120. * Time: O(\log N)
  121. * Source:
  122. * http://codeforces.com/blog/entry/18051
  123. * KACTL
  124. * Verification: SPOJ Fenwick
  125. */
  126.  
  127. template<class T> struct Seg { // comb(ID,b) = b
  128. const T ID = 0; T comb(T a, T b) { return max(a,b); }
  129. int n; vector<T> seg;
  130. void init(int _n) { n = _n; seg.assign(2*n,ID); }
  131. void pull(int p) { seg[p] = comb(seg[2*p],seg[2*p+1]); }
  132. void upd(int p, T val) { // set val at position p
  133. seg[p += n] = val; for (p /= 2; p; p /= 2) pull(p); }
  134. T query(int l, int r) { // sum on interval [l, r]
  135. T ra = ID, rb = ID;
  136. for (l += n, r += n+1; l < r; l /= 2, r /= 2) {
  137. if (l&1) ra = comb(ra,seg[l++]);
  138. if (r&1) rb = comb(seg[--r],rb);
  139. }
  140. return comb(ra,rb);
  141. }
  142. };
  143. Seg<int> S;
  144.  
  145. int n,rp[MX];
  146. vi p,q;
  147.  
  148. int getMax(int r) {
  149. int t = S.query(1,r); assert(t);
  150. return rp[t];
  151. }
  152.  
  153. int main() {
  154. setIO();
  155. re(n);
  156. p.rsz(n); re(p);
  157. q.rsz(n); re(q);
  158. S.init(1<<19);
  159. F0R(i,n) {
  160. S.upd(i+1,p[i]);
  161. rp[p[i]] = i+1;
  162. }
  163. L.upd(1,n,-MOD);
  164. trav(t,q) { // query max over range
  165. pr(S.query(1,n),' ');
  166. L.upd(t,t,MOD);
  167. L.upd(t,n,1);
  168. int x = L.firstGre();
  169. int z = getMax(x);
  170. L.upd(z,n,-1); S.upd(z,0);
  171. } //
  172. // you should actually read the stuff at the bottom
  173. }
  174.  
  175. /* stuff you should look for
  176. * int overflow, array bounds
  177. * special cases (n=1?)
  178. * do smth instead of nothing and stay organized
  179. * WRITE STUFF DOWN
  180. */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement