题意
思路:
首先可以感觉到是二分
进而可以发现是整体二分
警告:后面做法极为骚气,请各位站稳扶牢
这里的插入操作可以看成每一次的区间加(如果l>r可拆为两边处理)
最后可强行加一个覆盖所有点的区间加1e9,这样能满足所有p[i]
这里的询问操作可以看成询问每一个点的权值
对于整体二分基本与其他的相同,
不同的是需要扫整个区间,对区间内的每个国家收集到的陨石数进行统计,设它为num
若num>=p[i],直接将它装入左半部分递归
若num<p[i],则需p[i]-=num,然后再进入右半部分递归
具体实现:
对于区间加单点查询可使用差分的树状数组
用flag数组记录每个点所属国家在此次陨石收集过程中是否已被满足
很好。然鹅提交上去总会WA几个点
于是乎发现加的时候会爆int,于是乎开long long
于是乎发现又WA,于是乎发现加的时候连long long都会爆
怎么办呢?回首一看p[i]<=1e9。加到1e9不加了不就好了吗。
注意事项:
相加的时候的数据范围。
code:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=3e5+5;
int n,m,k,cnt;
int o[N],flag[N],ans[N];
ll gt[N],p[N];
struct node{int l,r,v,id,tp;}q[N*3],q1[N*3],q2[N*3];
inline int read()
{
int s=0,w=1; char ch=getchar();
for(;'0'>ch||ch>'9';ch=getchar())if(ch=='-')w=-1;
for(;'0'<=ch&&ch<='9';ch=getchar())s=(s<<1)+(s<<3)+(ch^48);
return s*w;
}
struct tree{
ll c[N];
inline int lowbit(int x){return x&(-x);}
inline void add(int x,ll y)
{
for(;x<=m;x+=lowbit(x))c[x]+=y;
}
inline ll query(int x)
{
ll anss=0;
for(;x;x-=lowbit(x))anss+=c[x];
return anss;
}
}T;
void solve(int L,int R,int l,int r)
{
if(l>r) return;
if(L==R)
{
for(int i=l;i<=r;++i)
if(q[i].tp==2) ans[q[i].id]=L;
return;
}
for(int i=l;i<=r;++i)if(q[i].tp==2)gt[q[i].id]=0,flag[q[i].id]=-1;
int mid=L+R>>1,cnt1=0,cnt2=0;
for(int i=l;i<=r;++i)
{
if(q[i].tp==1)
{
if(q[i].id<=mid)
T.add(q[i].l,1ll*q[i].v),T.add(q[i].r+1,-1ll*q[i].v),q1[++cnt1]=q[i];
else q2[++cnt2]=q[i];
}
else gt[q[i].id]=min(1000000001ll,gt[q[i].id]+T.query(q[i].l));
}
for(int i=l;i<=r;++i)
{
if(q[i].tp==1)
{
if(q[i].id<=mid) T.add(q[i].l,-1ll*q[i].v),T.add(q[i].r+1,1ll*q[i].v);
continue;
}
int pos=q[i].id;
if(flag[pos]==1) q1[++cnt1]=q[i];
else if(flag[pos]==0) q2[++cnt2]=q[i];
else
{
if(gt[pos]>=p[pos]) flag[pos]=1,q1[++cnt1]=q[i];
else p[pos]-=gt[pos],flag[pos]=0,q2[++cnt2]=q[i];
}
}
for(int i=l;i<=l+cnt1-1;++i) q[i]=q1[i-l+1];
for(int i=l+cnt1;i<=r;++i) q[i]=q2[i-l-cnt1+1];
solve(L,mid,l,l+cnt1-1);
solve(mid+1,R,l+cnt1,r);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=m;++i)o[i]=read();
for(int i=1;i<=n;++i)p[i]=1ll*read();
k=read();
for(int i=1;i<=k;++i)
{
int li=read(),ri=read(),ai=read();
if(li<=ri) q[++cnt]=node{li,ri,ai,i,1};
else
{
q[++cnt]=node{1,ri,ai,i,1};
q[++cnt]=node{li,m,ai,i,1};
}
}
q[++cnt]=node{1,m,1e9,k+1,1};
for(int i=1;i<=m;++i)q[++cnt]=node{i,0,0,o[i],2};
solve(1,k+1,1,cnt);
for(int i=1;i<=n;++i)
{
if(ans[i]==k+1||ans[i]==0) puts("NIE");
else printf("%d
",ans[i]);
}
return 0;
}