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。
数据范围: 1<=n,m,k<=3*10^5 1<=Pi<=10^9 1<=Ai<10^9
分析:
对于每一个国家我们可以二分一个答案。对于一个答案
m
i
d
mid
mid,我们把
l
l
l到
m
i
d
mid
mid的操作做了,然后枚举这个国家所有属于他的位置进行询问。因为每个位置只属于一个国家,最多询问
l
o
g
log
log次。可以使用树状数组维护区间加单点询问。复杂度是
O
(
n
l
o
g
2
n
)
O(nlog^2n)
O(nlog2n)的。
代码:
// luogu-judger-enable-o2
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#define LL long long
const int maxn=3e5+7;
using namespace std;
int n,m,x,T;
int ans[maxn];
LL t[maxn];
vector <int> e[maxn];
struct que{
int x,k;
}q[maxn],L[maxn],R[maxn];
struct rec{
int l,r,k;
}a[maxn];
void updata(int x,int k)
{
for (int i=x;i<=m;i+=i&(-i)) t[i]+=(LL)k;
}
LL query(int x)
{
LL sum=0;
for (int i=x;i>0;i-=i&(-i)) sum+=t[i];
return sum;
}
void ins(int l,int r,int k)
{
updata(l,k);
if (r<m) updata(r+1,-k);
}
void solve(int l,int r,int ql,int qr)
{
if (ql>qr) return;
if (l==r)
{
for (int i=ql;i<=qr;i++) ans[q[i].x]=l;
return;
}
int mid=(l+r)/2;
for (int i=l;i<=mid;i++)
{
if (a[i].l<=a[i].r) ins(a[i].l,a[i].r,a[i].k);
else ins(a[i].l,m,a[i].k),ins(1,a[i].r,a[i].k);
}
int cnt1=0,cnt2=0;
for (int i=ql;i<=qr;i++)
{
int x=q[i].x;
LL sum=0;
for (int j=0;j<e[x].size();j++)
{
int y=e[x][j];
sum+=query(y);
if (sum>=q[i].k) break;
}
if (sum>=q[i].k) L[++cnt1]=q[i];
if (sum<q[i].k) q[i].k-=(int)sum,R[++cnt2]=q[i];
}
for (int i=l;i<=mid;i++)
{
if (a[i].l<=a[i].r) ins(a[i].l,a[i].r,-a[i].k);
else ins(a[i].l,m,-a[i].k),ins(1,a[i].r,-a[i].k);
}
for (int i=1;i<=cnt1;i++) q[ql+i-1]=L[i];
for (int i=1;i<=cnt2;i++) q[ql+cnt1+i-1]=R[i];
solve(l,mid,ql,ql+cnt1-1);
solve(mid+1,r,ql+cnt1,qr);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=m;i++)
{
scanf("%d",&x);
e[x].push_back(i);
}
for (int i=1;i<=n;i++)
{
scanf("%d",&x);
q[i]=(que){i,x};
}
scanf("%d",&T);
for (int i=1;i<=T;i++) scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k);
solve(1,T+1,1,n);
for (int i=1;i<=n;i++)
{
if (ans[i]>T) printf("NIE\n");
else printf("%d\n",ans[i]);
}
}