문제 풀이

[BOJ] 13537 | 수열과 쿼리 1

문제

https://www.acmicpc.net/problem/13537

풀이

수열을 다음과 같은 업데이트 쿼리로 해석한다.

a b : 위치가 a인 위치를 b로 교체

그리고 쿼리 (i j k)를 k에 대해 내림차순으로 정렬한다.

업데이트 쿼리들도 마찬가지로, b에 대해 내림차순으로 정렬한다.

그리고, k>b를 만족할때, 세그먼트 트리에서 위치가 a인 곳에 1을 업데이트 한다.

그러면, 트리에서 i부터 j까지의 합이 쿼리 (i j k)에 대한 답변이 된다.

출력할때도, 쿼리의 입력순으로 정렬해주자.

소스

#include<iostream>
#include<vector>
#include<algorithm>
#include<functional>
#define ll long long
using namespace std;

struct _ { ll idx, i, j, k; };
bool operator<(_ a, _ b) { return a.k > b.k; }
vector<_> query;
vector<pair<ll, ll> >arr, ans;
ll N, MAX, tree[400000], M;

void update(ll p, ll v) {
	p += MAX;
	tree[p] = v;
	for (; p /= 2; tree[p] = tree[2 * p] + tree[2 * p + 1]);
}

ll sum(ll s, ll e) {
	ll res = 0;
	s += MAX, e += MAX;
	while (s < e) {
		if (s % 2)
			res += tree[s++];
		if (e % 2 == 0)
			res += tree[e--];
		e /= 2;
		s /= 2;
	}
	if(s==e)
		res += tree[e];
	return res;
}

int main() {
	ios::sync_with_stdio(0); cin.tie(0);
	cin >> N;
	for (MAX = 1; MAX < N; MAX *= 2);
	for (int i = 1; i <= N; i++) {
		ll tmp;
		cin >> tmp;
		arr.push_back({ tmp,i });
	}
	cin >> M;
	for (int i = 0; i < M; i++) {
		ll a, b, c;
		cin >> a >> b >> c;
		query.push_back({ i,a,b,c });
	}
	sort(arr.begin(), arr.end(), greater<pair<ll, ll> >() );
	sort(query.begin(), query.end());
	ll now = 0;
	for (auto idx : query) {
		while (now < arr.size() && idx.k < arr[now].first) {
			update(arr[now].second, 1);
			now++;
		}
		ans.push_back({ idx.idx, sum(idx.i,idx.j) });
	}
	sort(ans.begin(), ans.end());
	for (auto idx : ans)
		cout << idx.second << "\n";
}
← 문제 풀이 글 더 보기