BOJ 16532, ICPC Latin 2018 Looking for the Risk Factor
ํ์ด
๋ฌธ์ ๋ฅผ ์์ฝํ์๋ฉด, ๋งค ์ฟผ๋ฆฌ $(x, y)$ ๋ง๋ค, 2๋ถํฐ $x$๊น์ง์ ์ ์ค ์์ธ์๊ฐ ๋ชจ๋ $y$ ์ดํ์ธ ์์ ๊ฐ์๋ฅผ ์ธ๋ ๋ฌธ์ ์ด๋ค. ๋๊ฐ์ง ์๋ก ๋ค๋ฅธ ์ฐ๋ ธ์ด ๋ฌธ์ ๋ฅผ ์ ํด๊ฒฐํ ์ ์๋ค๋ฉด ํฉ์ณ์ ์ด๋ ต์ง ์๊ฒ ํด๊ฒฐํ ์ ์๋ค.
- ์๋ผํ ์คํ ๋ค์ค์ ์ฒด๋ฅผ ์ด์ง ์์ฉํ๋ฉด, 2๋ถํฐ $M$ ๊น์ง์ ์ฃผ์ด์ง ์๋ค์ ๋ํด์ ๊ฐ์ฅ ํฐ ์์ธ์ ๋ฅผ ์ ๋ถ ์ฐพ๋๋ฐ $O(n \log \log n)$ ์๊ฐ์ด ๊ฑธ๋ฆฐ๋ค. ์์ธ์๋ถํด ์ฒด์ ๊ฑฐ์ ๋๊ฐ๊ณ ํ๋์ค๋ง ๋ฐ๊พธ๋ฉด ๋๋ค.
-
์ด์ , ๊ฐ์ฅ ํฐ ์์ธ์ ๋ฅผ ๋ชจ๋ ์์์ผ๋ฏ๋ก, ์ด๋ค ์์ด์ด ์ฃผ์ด์ก์ ๋ ๋ฌธ์ ๋ $[2, x]$ ๊น์ง์ ์ธ๋ฑ์ค๋ค ์ค $a_i \leq y$ ์ธ ์๋ค์ ๊ฐ์๋ฅผ ์ธ๋ ๋ฌธ์ ๊ฐ ๋๋ค. ์ด๋ ์์ด๊ณผ ์ฟผ๋ฆฌ 3 ๋ฌธ์ ์ ๋น์ทํ๋ฐ (์์ ์ธ๋ฑ์ค๊ฐ ๊ณ ์ ๋์ด ์์ผ๋ฏ๋ก ์กฐ๊ธ ๋ ์ฝ๋ค), ํฌ๊ฒ ๋ ๊ฐ์ง ๋ฐฉ๋ฒ์ผ๋ก ํ ์ ์๋ค.
- ์ฟผ๋ฆฌ๋ฅผ ์ ๋ ฌํด์, ์คํ๋ผ์ธ์ผ๋ก ํ ์ ์๋ค. ์ด๋ ๊ฒ ํ๋ฉด ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ํ์ ํธ๋ฆฌ ๊ฐ์ ๊ฑธ๋ก, ์์๋ ์๊ณ ์๊ฐ๋ณต์ก๋๋ $O(n \log n)$ ์ ์ ์งํ ์ ์๋ค.
- ๋จธ์ง ์ํธ ํธ๋ฆฌ๋ฅผ ์ฐ๋ฉด ์จ๋ผ์ธ์ผ๋ก๋ ํ ์ ์๋ค. ๋จธ์ง ์ํธ ํธ๋ฆฌ์ ๋ํด์๋ ์ธ์ ๊ฐ ๊ธ์ ์ธ ์๋ ์๋๋ฐ, ๋๋ต์ ์ผ๋ก ์ค๋ช
ํ์๋ฉด ๋จธ์ง์ํธ๋ฅผ ์ํํ๋ ์ค๊ฐ ๊ณผ์ ์ ๋ชจ๋ ์ค์ ๋ก ํธ๋ฆฌ์ ํํ๋ก ๋ค๊ณ ์๋ ์๋ฃ๊ตฌ์กฐ์ด๋ค. ๋น๋๋ merge๋ฅผ ์ฐ๋์ง ๋์ถฉ ํ๋์ง ์ฌ๋ถ์ ๋ฐ๋ผ ์ ๋ง ์ฝ๊ฒ ์ฝ๋ฉํ๊ณ ์ถ์ผ๋ฉด $O(n \log^2 n)$ ์๊ฐ์ ํธ๋ฆฌ๋ฅผ ๋น๋ํด๋ ๋๊ณ , ์ง์ง ๋จธ์ง์ํธ๋ฅผ ์ฐ๋ฉด $O(n \log n)$ ์๊ฐ์ ๋น๋ํด๋ ๋๋ค. ์๋ ์ฝ๋๋ $n \log n$ ๋น๋.
- ์ด์ , ๋จธ์ง ์ํธ ํธ๋ฆฌ๋ $[i, j]$ ์์ $k$ ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์์ ๊ฐ์ (์์ฟผ3) ํํ์ ์ฟผ๋ฆฌ๋ฅผ
lower_bound, upper_bound
๊ฐ์ STL ํจ์๋ค๋ก ๋น ๋ฅด๊ฒ ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ, ํ๋ฒ ์ฟผ๋ฆฌ์์ ์ด ํจ์๋ค์ ์ต๋ $O(\log n)$ ๋ฒ ํธ์ถํ๋ฏ๋ก ๋งค ์ฟผ๋ฆฌ๋ฅผ $O(\log^2 n)$์ ์ฒ๋ฆฌํ๋ ์ ์ด ๋๋ค. - ์ฟผ๋ฆฌ๋ ์ธ๊ทธ๋จผํธ ํธ๋ฆฌ๋ ๊ฑฐ์ ๋๊ฐ์ ๋๋์ผ๋ก ์ฟผ๋ฆฌํ๋ค. ํ๋ฒ ์ฝ์ด๋ณด๋ฉด ๋์ถฉ ์ด๋ค ๋๋์ ์๋ฃ๊ตฌ์กฐ์ธ์ง ์๊ธฐ ์ด๋ ต์ง ์๋ค.
- ์ด์ , ๋จธ์ง ์ํธ ํธ๋ฆฌ๋ $[i, j]$ ์์ $k$ ๋ณด๋ค ์๊ฑฐ๋ ๊ฐ์ ์์ ๊ฐ์ (์์ฟผ3) ํํ์ ์ฟผ๋ฆฌ๋ฅผ
์๋ ์ฝ๋๋ ๋จธ์ง์ํธํธ๋ฆฌ, $O(n \log n)$ ๋ฒ์ ์ผ๋ก ์์ฑ๋์ด ์๋ค.
์ฝ๋
#include <bits/stdc++.h>
#pragma GCC optimize("O3")
#pragma GCC optimize("Ofast")
#pragma GCC target("avx,avx2,fma")
#define ll long long
#define eps 1e-7
#define all(x) ((x).begin()),((x).end())
#define usecppio ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
using namespace std;
#define int ll
using pii = pair<int, int>;
#define MAXN (1<<18)
struct merge_sort_tree
{
vector <int> tree[MAXN];
int n;
void construct (vector <int> data)
{
n = 1;
while(n < data.size()) n <<= 1;
for (int i = 0; i<data.size(); i++)
tree[i+n] = {data[i]};
for (int i = data.size(); i<n; i++)
tree[i+n] = {};
for (int i = n-1; i>0; i--)
{
tree[i].resize(tree[i*2].size()+tree[i*2+1].size());
for (int p = 0, q = 0, j = 0; j < tree[i].size(); j++)
{
if (p == tree[i*2].size() || (q<tree[i*2+1].size() && tree[i*2+1][q]<tree[i*2][p]))
tree[i][j] = tree[i*2+1][q++];
else tree[i][j] = tree[i*2][p++];
}
}
}
int greater(int s, int e, int k, int node, int ns, int ne)
{
if (ne <= s || ns >= e)
return 0;
if(s <= ns && ne <= e)
return tree[node].end() - upper_bound(all(tree[node]), k);
int mid = (ns+ne)>>1;
return greater(s,e,k,node*2,ns,mid) + greater(s,e,k,node*2+1,mid,ne);
}
int greater(int s, int e, int k)
{
return greater(s,e,k,1,0,n);
}
};
int M = 100000;
int lpd[101010];
vector <int> v(M, 0);
int32_t main()
{
usecppio
for (int i = 2; i <= M; i++)
{
if (lpd[i]) continue;
for (int j = i; j <= M; j += i)
lpd[j] = i;
}
for (int i = 1; i <= M; i++)
v[i-1] = lpd[i];
merge_sort_tree t;
t.construct(v);
int q; cin >> q;
while(q--)
{
int n, k; cin >> n >> k;
cout << n - t.greater(0, n, k) - 1 << '\n';
}
}