Luogu3527 POI2011 Meteors 整體二分、樹狀陣列、差分
阿新 • • 發佈:2019-01-06
比較板子的整體二分題目,時限有點緊注意常數
整體二分的過程中將時間在\([l,mid]\)之間的流星使用樹狀陣列+差分進行維護,然後對所有國家檢視一遍並分好類,遞迴下去,記得消除答案在\([mid+1,r]\)的詢問中時間在\([l,mid]\)的流星操作的貢獻
注意:可能存在某一段時間某一個國家的流星數量超過long long範圍,應該當某個時候國家流星量和大於等於國家需求值時直接退出,這樣可以避免這個問題。
#include<bits/stdc++.h> #define INF 0x7fffffff #define lowbit(x) ((x) & -(x)) using namespace std; inline int read(){ int a = 0; char c = getchar(); while(!isdigit(c)) c = getchar(); while(isdigit(c)){ a = a * 10 + c - 48; c = getchar(); } return a; } const int MAXN = 3e5 + 10; vector < int > bel[MAXN]; long long BIT[MAXN]; int qry[MAXN][2] , tp[2][MAXN][2] , mod[MAXN][3] , ans[MAXN]; int N , M , K; inline void add(int p , int num){ while(p <= M){ BIT[p] += num; p += lowbit(p); } } inline long long get(int p){ long long sum = 0; while(sum < 1e9 && p){ sum += BIT[p]; p -= lowbit(p); } return sum; } void solve(int ql , int qr , int l , int r){ if(qr < ql) return; if(l == r){ for(int i = ql ; i <= qr ; ++i) ans[qry[i][0]] = l; return; } int mid = (l + r) >> 1 , p0 = 0 , p1 = 0; for(int i = l ; i <= mid ; ++i){ add(mod[i][1] + 1 , -mod[i][2]); add(mod[i][0] , mod[i][2]); if(mod[i][0] > mod[i][1]) add(1 , mod[i][2]); } for(int i = ql ; i <= qr ; ++i){ long long sum = 0; for(int j = 0 ; j < bel[qry[i][0]].size() && sum < qry[i][1] ; ++j) sum += get(bel[qry[i][0]][j]); if(sum >= qry[i][1]){ tp[0][++p0][0] = qry[i][0]; tp[0][p0][1] = qry[i][1]; } else{ tp[1][++p1][0] = qry[i][0]; tp[1][p1][1] = qry[i][1] - sum; } } memcpy(qry + ql , tp[0] + 1 , sizeof(int) * p0 * 2); memcpy(qry + ql + p0 , tp[1] + 1 , sizeof(int) * p1 * 2); for(int i = l ; i <= mid ; ++i){ add(mod[i][1] + 1 , mod[i][2]); add(mod[i][0] , -mod[i][2]); if(mod[i][0] > mod[i][1]) add(1 , -mod[i][2]); } solve(ql , ql + p0 - 1 , l , mid); solve(ql + p0 , qr , mid + 1 , r); } signed main(){ N = read(); M = read(); for(int i = 1 ; i <= M ; ++i) bel[read()].push_back(i); for(int i = 1 ; i <= N ; ++i){ qry[i][0] = i; qry[i][1] = read(); } K = read(); for(int i = 1 ; i <= K ; ++i){ mod[i][0] = read(); mod[i][1] = read(); mod[i][2] = read(); } solve(1 , N , 1 , K + 1); for(int i = 1 ; i <= N ; ++i) if(ans[i] == K + 1) puts("NIE"); else printf("%d\n" , ans[i]); return 0; }