BOJ 22959 - 신촌 수열과 쿼리

image.png

뻔한 세그먼트 트리 문제이다.

문제를 잘 읽어보면 2번 쿼리에서 항상 $i$ 는 구간에 포함이 되어있어야 하는데, 그럼 $i$ 를기준으로 왼쪽으로 얼마나 $j$ 이상인 것이 긴지, 오른쪽으론 얼마나 긴지를 세그먼트 트리로 $O(\log ^2n)$ 혹은 $O(\log n)$ 으로 구할 수 있다.

다음과 같은 코드는 그냥 이분탐색으로 $O(\log ^2n)$ 으로 푼 것으로 시간안에 통과한다.

void solve() {
   int n;
   cin >> n;
   vi a(n);
   fv(a);
   seg_tree<int> seg(n);
   for (int i = 0; i < n; i++) seg.update(i, a[i]);
   int q;
   cin >> q;
   while (q--) {
      int c, i, j;
      cin >> c >> i >> j;
      i--;
      if (c == 1) {
         seg.update(i, j);
      } else {
         int lo = 0, hi = i, ret = i;
         while (lo <= hi) {
            int m = lo + hi >> 1;
            if (seg.query(m, i).min >= j) ret = m, hi = m - 1;
            else lo = m + 1;
         }
         int leftmost = ret;
         lo = i, hi = n - 1, ret = i;
         while (lo <= hi) {
            int m = lo + hi >> 1;
            if (seg.query(i, m).min >= j) ret = m, lo = m + 1;
            else hi = m - 1;
         }
         int rightmost = ret;
         cout << seg.query(leftmost, rightmost).sum << endl;
      }
   }
}

Tags:

Categories:

Updated:

Comments