这道题是整体二分的基础题,可以通过同时对所有询问进行二分,并且使得贡献值不用重复计算,所以使得效率很高
http://victorwonder.is-programmer.com/posts/70210.html 已经讲得很清楚了
code:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson l,mid
#define rson mid+1,r
#define Mid int mid = (l + r) >> 1
using namespace std;
typedef long long LL;
const int N = 300005;
const int INF = 1e9;
int q[N],ql[N],qr[N];
int oo[N],next[N];
int ans[N],m;
int L[N],R[N],C[N];
LL p[N],cur[N];
LL sum[N];
LL query(int c){
LL res = 0;
for(int i = c ; i ; i -= (i & -i))
res += sum[i];
return res;
}
void add(int c,LL v){
for(int i = c ; i <= m ; i += (i & -i))
sum[i] += v;
}
void addt(int l,int r,LL v){
if(l <= r){
add(l,v);
add(r + 1,-v);
}
else{
add(1,v);
add(r + 1,-v);
add(l,v);
}
}
void solve(int head,int tail,int l,int r){
if(l == r){
for(int i = head ; i <= tail ; i ++){
ans[ q[i] ] = l;
}
return;
}
Mid;
int l1,l2;
l1 = l2 = 0;
for(int i = l ; i <= mid ; i ++) addt(L[i],R[i],C[i]);
for(int i = head ; i <= tail ; i ++){
LL tmp = 0,u = q[i];
for(int j = oo[u] ; j ; j = next[j]){
tmp += query(j);
if(tmp + cur[u] >= p[u]) break;
}
if(tmp + cur[u] >= p[u]) ql[l1 ++] = u;
else qr[l2 ++] = u,cur[u] += tmp;
}
for(int i = l ; i <= mid ; i ++) addt(L[i],R[i],-C[i]);
for(int i = 0 ; i < l1 ; i ++) q[head + i] = ql[i];
for(int i = 0 ; i < l2 ; i ++) q[head + l1 + i] = qr[i];
solve(head,head + l1 - 1,lson);
solve(head + l1,tail,rson);
}
int main()
{
int n,o,k;
scanf("%d%d",&n,&m);
for(int i = 1 ; i <= m ; i ++){
scanf("%d",&o);
next[i] = oo[o];
oo[o] = i;
}
for(int i = 1 ; i <= n ; i ++){
q[i] = i;
scanf("%d",&p[i]);
}
scanf("%d",&k);
for(int i = 1 ; i <= k ; i ++)
scanf("%d%d%d",&L[i],&R[i],&C[i]);
k ++;
solve(1,n,1,k);
for(int i = 1 ; i <= n ; i ++){
if(ans[i] < k) printf("%d\n",ans[i]);
else printf("NIE\n");
}
return 0;
}