码迷,mamicode.com
首页 > 其他好文 > 详细

【CDQ或并行二分】 SPOJ METEORS

时间:2015-10-11 19:24:16      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

通道

题意:有m个空间站组成一个环形的轨道,每个空间站属于n个国家之一。一次流星雨可以给一段连续的空间站带来同样数量的陨石样本。给出每个国家需要的陨石数量和流星雨的出现情况,问每个国家最快在多少次流星雨前就能收集到需要数量的陨石

思路:分别二分算出答案即可

代码:

技术分享
#include <algorithm>
#include <vector>
#include <cstdio>
#include <cstring>
#define  RD(x)      scanf("%d", &x)
#define  REP(i, n)  for (int i=0; i<int(n); i++)
#define  FOR(i, n)  for (int i=1; i<=int(n); i++)
#define  pii        pair<int, int>
#define  mp         make_pair
#define  pb         push_back
int read(){int ret; scanf("%d", &ret); return ret;}

using namespace std;
#define  N   345678
#define  M   22222
#define  eps 1e-8
#define  pi  acos(-1.0)
#define  inf 0X5FFFFFFFFFFFFFFFll
#define  mod 1000000007ll
#define  LL  long long
#define  ULL unsigned long long

LL add[N];
int n, m, K;
int color[N], C;

void update(int x, LL val) {
    while (x <= m) {
        if (color[x] != C) add[x] = 0;
        color[x] = C;
        add[x] += val;
        x += x & (-x);
    }
}

void update(int l, int r, LL val) {
    update(l, val);
    update(r+1, -val);
}
LL get(int x) {
    LL ret = 0;
    while (x > 0) {
        if (color[x] == C) ret += add[x];
        x -= x & (-x);
    }
    return ret;
}

LL p[N];
int l[N], r[N];
LL w[N];

void update(int id) {
    if (l[id] <= r[id])
        update(l[id], r[id], w[id]);
    else
        update(1, r[id], w[id]), update(l[id], m, w[id]);
}

vector<int> has[N];
int lans[N], rans[N], mans[N];
pii a[N];
bool suc[N];

void parallelbinarysearch() {
    int all = 0;
    FOR(i, n) if (lans[i] != rans[i]) {
        a[all].first = mans[i];
        a[all].second = i;
        all++;
    }
    sort(a, a + all);
    ++C;
    int t = 1;
    REP(i, all) {
        int id = a[i].second;
        while (t <= K && t <= a[i].first)
            update(t++);
        LL tmp = 0;
        suc[id] = false;
        REP(j, has[id].size()) {
            tmp += get(has[id][j]);
            if (tmp >= p[id])
                suc[id] = true;
        }
    }

}

int Main() {
    RD(n);
    RD(m);

    FOR(i, m) {
        int x;
        RD(x);
        has[x].push_back(i);
    }

    FOR(i, n)
        p[i] = read();

    RD(K);
    FOR(i, K) {
        RD(l[i]);
        RD(r[i]);
        w[i] = read();
    }

    FOR(i, n)
        lans[i] = 1, rans[i] = K+1;

    while (true) {

        FOR(i, n)
            mans[i] = (lans[i] + rans[i]) >> 1;

        parallelbinarysearch();

        FOR(i, n) if (lans[i] != rans[i]) {
            if (suc[i])
                rans[i] = mans[i];
            else
                lans[i] = mans[i] + 1;
        }

        bool ok = true;
        FOR(i, n)
            if (lans[i] != rans[i])
                ok = false;
        if (ok)
            break;
    }
    FOR(i, n)
        if (lans[i] <= K)
            printf("%d\n", lans[i]);
        else
            puts("NIE");

    return 0;
}


int main() {
    return Main();
}
View Code

 

【CDQ或并行二分】 SPOJ METEORS

标签:

原文地址:http://www.cnblogs.com/Rojo/p/4869751.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!