본문으로 바로가기

8217 유성 (Meteors)

category PS - OJ/BOJ 2016. 11. 19. 16:24

유성 (8217 Meteors)

https://www.acmicpc.net/problem/8217 (BOJ Meteors)

http://www.spoj.com/problems/METEORS (SPOJ Meteors)

http://codeforces.com/blog/entry/45578 (Codeforces parellel binary search tutorial)




블로그 만든 기념으로 최근에(거의 한달 전인 것 같지만) 풀었던 문제중 꽤 난이도가 있었던 문제를 올려본다. ㅎ


이 문제 번역도 내가했다 ㅋㅋ

번역글 도저히 못보겠다 생각되면 원문을 보시길 바랍니다. (ㅈㅅㅈㅅ)


parallel binary search(pbs) 알고리즘으로 푸는 가장 대표적인 문제인 것 같다.

코드포스 가서 pbs검색해보면 제일 처음에 포스팅 된 글에서 meteors 문제를 통해 설명하는 것을 볼 수 있다.



근데, 코딩한지 너무 오래돼서 어디서 버벅였는지 기억이 안난다. ㅋㅋ


일단 펜윅을 썼는데, 처음에 Petr가 소개하는 Fenwick Range Update를 그대로 가져와서 쓰다가, 쿠사과님의 조언으로 그런짓을 할 필요가 없다는 걸 알게 됐다. 여기서 펜윅 구간 업뎃을 그대로 쓰면 unsigned long long 범위마저 초과해서 답이 없다. 그렇다고 Segment Tree를 쓰자니 메모리를 많이 먹는다. 내 기억엔 BOJ 메모리 부분이 세그먼트 트리를 쓰면 메모리초과가 났던 걸로 기억하는데, 정확하지는 않다.


아무튼 그래서 펜윅을 응용해서 자료구조 만들고, 나머지 pbs는 그냥 전형적인 pbs 코딩을 하면 된다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
#include <cstdio>
#include <vector>
using namespace std;
typedef unsigned long long ull;
vector<int> sect[300001];
vector<vector<int> > cp;
ull goal[300001];
struct Day{
    int l,r; ull cnt;
    Day(){} Day(int l, int r, ull cnt):l(l),r(r),cnt(cnt){}
};
struct Fenwick{
    int s,e;
    vector<ull> tree, tadd;
    Fenwick(){} Fenwick(int n):s(1),e(n),tree(n+1,0ULL){}
    void clear() { tree.clear(); tree.resize(e+1,0ULL); }
    void rupdate(int left, int right, ull by) {
        inupdate(left, by);
        inupdate(right+1-by);
    }
    void inupdate(int at, ull by) {
        for(int i=at; i<=&& i; i+=i&-i) tree[i]+=by;
    }
    ull query(int at) {
        ull ans=0ULL;
        for(int i=at; i>=1; i&=(i-1)) ans+=tree[i];
        return ans;
    }
};
 
vector<Day> day(1);
int l[300001], r[300001];
int main() {
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1; i<=m; i++) {
        int x; scanf("%d",&x);
        sect[x].push_back(i);
    }
    Fenwick fen(m);
    for(int i=1; i<=n; i++) {
        scanf("%llu",&goal[i]);
    }
    int q; scanf("%d",&q);
    for(int i=1; i<=q; i++) {
        int l,r; ull cnt;
        scanf("%d%d%llu",&l,&r,&cnt);
        day.push_back(Day(l,r,cnt));
    }
    cp.resize(q+1, vector<int>());
    for(int i=1; i<=n; i++) l[i]=0, r[i]=q+1;
    while(true) {
        bool good=false;
        for(int i=1; i<=n; i++) {
            if(l[i]+1<r[i]) {
                cp[(l[i]+r[i])>>1].push_back(i);
                good=true;
            }
        }
        if(!good) break;
 
        int pi=1;
        for(int i=1; i<=q; i++) {
            //bring meteor shower!!
            if(!cp[i].size()) continue;
            for(int j=pi; j<=i; pi=++j) {
                if(day[j].l<=day[j].r) {
                    fen.rupdate(day[j].l,day[j].r,day[j].cnt);
                } else {
                    fen.rupdate(1,day[j].r,day[j].cnt);
                    fen.rupdate(day[j].l,m,day[j].cnt);
                }
            }
 
            for(int nara: cp[i]) {
                ull sum=0ULL;
                for(int k: sect[nara]) sum+=fen.query(k);
                int mid=(l[nara]+r[nara])>>1;
                if(sum>=goal[nara]) r[nara]=mid;
                else l[nara]=mid;
            }
            cp[i].clear();
        }
        fen.clear();
    }
 
    for(int i=1; i<=n; i++) {
        if(r[i]!=q+1printf("%d\n", r[i]);
        else puts("NIE");
    }
    return 0;
}
 
cs


'PS - OJ > BOJ' 카테고리의 다른 글

BOJ 14265 영선 수열  (0) 2017.01.14
1280 나무심기  (0) 2016.12.26
알고리즘 문제풀이(PS) 시작하기  (365) 2016.12.23
1328 고층빌딩  (0) 2016.12.09
13333 Q-인덱스 (Q-Index)  (0) 2016.12.09