parallel binary search SPOJMeteors

来源:互联网 发布:淘宝网衣架 编辑:程序博客网 时间:2024/06/14 06:12

题目链接

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

解题思路:离线、并行二分搜索。首先可以二分判断每个国家的答案。“并行”在这里是一个形象的比喻,即判断(MID)答案是否正确时可以在O(n)的时间内判断出每个国家的答案。

该题中间计算结果会超过64位整数,wa了许久。。

#include <algorithm>#include <cmath>#include <cstdio>#include <cstring>#include <iomanip>#include <iostream>#include <cassert>#include <map>#include <set>#include <queue>#include <stack>#include <vector>#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_backinline   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 longLL add[N];int n, m, K;void buildtree() {memset(add, 0, sizeof add);}void update(int x, LL val) {while (x <= m) {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) {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]);elseupdate(1, r[id], w[id]), update(l[id], m, w[id]);}vector<int> has[N];int lans[N], rans[N], mans[N];bool suc[N];void parallelbinarysearch() {static pii a[N];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);buildtree();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];elselans[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]);elseputs("NIE");return 0;}int main() {return Main();}


0 0
原创粉丝点击