Byteotian Interstellar Union有N个成员国。现在它发现了一颗新的星球,这颗星球的轨道被分为M份(第M份和第1份相邻),第i份上有第Ai个国家的太空站。
这个星球经常会下陨石雨。BIU已经预测了接下来K场陨石雨的情况。
BIU的第i个成员国希望能够收集Pi单位的陨石样本。你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石。
输入:
第一行是两个数N,M。
第二行有M个数,第i个数Oi表示第i段轨道上有第Oi个国家的太空站。
第三行有N个数,第i个数Pi表示第i个国家希望收集的陨石数量。
第四行有一个数K,表示BIU预测了接下来的K场陨石雨。
接下来K行,每行有三个数Li,Ri,Ai,表示第K场陨石雨的发生地点在从Li顺时针到Ri的区间中(如果Li<=Ri,就是Li,Li+1,…,Ri,否则就是Ri,Ri+1,…,m-1,m,1,…,Li),向区间中的每个太空站提供Ai单位的陨石样本。
输出: N行。第i行的数Wi表示第i个国家在第Wi波陨石雨之后能够收集到足够的陨石样本。如果到第K波结束后仍然收集不到,输出NIE。
这道题答案很明显满足二分性,但是是多个询问,所以要整体二分。建议大家学过整体二分之后再来捉此题。那之后难点就变成如何check了,那很明显是树状数组嘛,改段求点,每个国家暴力判断是否满足就可以了。NIE的情况只要上限+1,之后如果答案为上限+1,那就是NIE了,最后记得开long long,wy在累加过程中有可能爆long long,所以要边加边判断。那这题就解决了。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
using namespace std;
struct node
{
int l,r,d;long long k;
}b[310000],q[310000],t[310000];
struct bian
{
int x,y,next;
}a[610000];int len,last[310000];
void ins(int x,int y)
{
len++;
a[len].x=x;a[len].y=y;
a[len].next=last[x];last[x]=len;
}
int n,m;
long long s[310000];
int lowbit(int x){return x&-x;}
void add(int x,long long k)
{
while(x<=m)
{
s[x]+=k;
x+=lowbit(x);
}
}
long long getsum(int x)
{
long long sum=0;
while(x>=1)
{
sum+=s[x];
x-=lowbit(x);
}
return sum;
}
int ans[310000];
void solve(int l,int r,int sl,int sr)
{
if(sl==sr)
{
for(int i=l;i<=r;i++)ans[b[i].d]=sl;
return ;
}
int mid=(sl+sr)/2;
for(int i=sl;i<=mid;i++)
{
if(q[i].l<=q[i].r)add(q[i].l,q[i].k),add(q[i].r+1,-q[i].k);
else add(q[i].l,q[i].k),add(1,q[i].k),add(q[i].r+1,-q[i].k);
}
int stl=l,str=r;
for(int i=l;i<=r;i++)
{
long long wy=0;int x=b[i].d;
for(int k=last[x];k;k=a[k].next)
{
int y=a[k].y;
wy+=getsum(y);
if(wy>=b[i].k)break;
}
if(wy>=b[i].k)t[stl++]=b[i];
else
{
b[i].k-=wy;
t[str--]=b[i];
}
}
for(int i=sl;i<=mid;i++)
{
if(q[i].l<=q[i].r)add(q[i].l,-q[i].k),add(q[i].r+1,q[i].k);
else add(q[i].l,-q[i].k),add(1,-q[i].k),add(q[i].r+1,q[i].k);
}
for(int i=l;i<=r;i++)b[i]=t[i];
if(stl!=l)solve(l,stl-1,sl,mid);
if(str!=r)solve(str+1,r,mid+1,sr);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
{
int x;
scanf("%d",&x);
ins(x,i);
}
for(int i=1;i<=n;i++)scanf("%lld",&b[i].k),b[i].d=i;
int kk;
scanf("%d",&kk);
for(int i=1;i<=kk;i++)scanf("%d%d%lld",&q[i].l,&q[i].r,&q[i].k);
solve(1,n,1,kk+1);
for(int i=1;i<=n;i++)
{
if(ans[i]==kk+1)printf("NIE\n");
else printf("%d\n",ans[i]);
}
return 0;
}