传送门biu~
整体二分,二分需要等多少场陨石雨能够收集足够。尤其需要注意此题数据需要double类型的树状数组才能过。别问我怎么知道的。
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
using namespace std;
int n,m,k,p,now;
int head[300005],nex[300005],q[300005],tmp[300005],ans[300005],needs[300005];
double tree[300005];
struct data{
int l,r;
double v;
}a[300005];
inline void add(int x,double v){
while(x<=m){
tree[x]+=v;
x+=lowbit(x);
}
}
inline void add(int l,int r,double v){
add(l,v);add(r+1,-v);
}
inline double search(int x){
double re=0;
while(x){
re+=tree[x];
x-=lowbit(x);
}
return re;
}
void binary_search(int l,int r,int x,int y){//将[l,r]的国家在[x,y]范围内二分答案
if(l>r || x>y) return;
int mid=x+y>>1;
while(now<mid){
++now;
if(a[now].l<=a[now].r) add(a[now].l,a[now].r,a[now].v);
else add(1,a[now].r,a[now].v),add(a[now].l,m,a[now].v);
}
while(now>mid){
if(a[now].l<=a[now].r) add(a[now].l,a[now].r,-a[now].v);
else add(1,a[now].r,-a[now].v),add(a[now].l,m,-a[now].v);
--now;
}
int nl=l,nr=r;
for(int i=l;i<=r;++i){
int x=q[i];
double re=0;
for(int j=head[x];j;j=nex[j]) re+=search(j);
if(re<needs[x]) tmp[nr--]=x;
else{
tmp[nl++]=x;
ans[x]=now;
}
}
memcpy(q+l,tmp+l,sizeof(q[0])*(r-l+1));
binary_search(l,nl-1,x,mid-1);
binary_search(nr+1,r,mid+1,y);
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
int x;
scanf("%d",&x);
nex[i]=head[x];
head[x]=i;
}
for(int i=1;i<=n;++i) scanf("%d",&needs[i]);
scanf("%d",&k);
for(int i=1;i<=k;++i) scanf("%d%d%lf",&a[i].l,&a[i].r,&a[i].v);
for(int i=1;i<=n;++i) q[i]=i;
binary_search(1,n,1,k);
for(int i=1;i<=n;++i){
if(!ans[i]) printf("NIE\n");
else printf("%d\n",ans[i]);
}
return 0;
}