比较板子的整体二分题目,时限有点紧注意常数
整体二分的过程中将时间在\([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;
}