标签:
题意:有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(); }
标签:
原文地址:http://www.cnblogs.com/Rojo/p/4869751.html