第一道整体二分,实际上就是锻炼分治思想
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
typedef long long ll;
const int N=300005;
const ll inf=1e9+10;
int n,m,k;
struct aa
{
ll p;int ans;
}c[N];
//
int head[N],to[N],pre[N],tot;
void addedge(int u,int v)
{
to[++tot]=v;pre[tot]=head[u];head[u]=tot;
}
///
struct aaa
{
int l,r;ll sum;bool clear;
}a[N*4];
void build(int i,int l,int r)
{
a[i].l=l,a[i].r=r;
if (l==r) return ;
int mid=(l+r)>>1;
build(i<<1,l,mid);
build(i<<1|1,mid+1,r);
}
void down(int i)
{
if (a[i].clear)
{
a[i<<1].sum=a[i<<1|1].sum=0;
a[i<<1].clear=a[i<<1|1].clear=true;
a[i].clear=false;
}
}
void updata(int i,int l,int r,ll add)
{
if (a[i].l==l&&a[i].r==r) {a[i].sum+=add;return;}
int mid=(a[i].l+a[i].r)>>1;
down(i);
if (r<=mid) updata(i<<1,l,r,add);
else if (mid<l) updata(i<<1|1,l,r,add);
else updata(i<<1,l,mid,add),updata(i<<1|1,mid+1,r,add);
}
ll query(int i,int pos)
{
if (a[i].l==a[i].r) return a[i].sum;
int mid=(a[i].l+a[i].r)>>1;
down(i);
if (pos<=mid) return query(i<<1,pos)+a[i].sum;
return query(i<<1|1,pos)+a[i].sum;
}
/
struct aaaa
{
int l,r;ll add;
}t[N];
int q[N],tmp[N];
void updata(int i)
{
if (t[i].l<=t[i].r) updata(1,t[i].l,t[i].r,t[i].add);
else updata(1,t[i].l,m,t[i].add),updata(1,1,t[i].r,t[i].add);
}
void clear()
{
a[1].sum=0;a[1].clear=true;
}
void work(int tl,int tr,int l,int r)
{
if (l>r) return ;
if (tl==tr)
{
for (int i=l;i<=r;i++) c[q[i]].ans=tl;
return ;
}
int mid=(tl+tr)>>1,ll=l,rr=r;
clear();
for (int i=tl;i<=mid;i++) updata(i);
for (int i=l;i<=r;i++)
{
long long ans=0;
for (int j=head[q[i]];j;j=pre[j])
{
ans+=query(1,to[j]);
if (ans>inf) break;
}
if (ans>=c[q[i]].p) tmp[ll++]=q[i];else tmp[rr--]=q[i],c[q[i]].p-=ans;
}
for (int i=l;i<=r;i++) q[i]=tmp[i];
work(tl,mid,l,rr);
work(mid+1,tr,ll,r);
}
int main()
{
scanf("%d%d",&n,&m);
int x;
for (int i=1;i<=m;i++)
{
scanf("%d",&x);
addedge(x,i);
}
for (int i=1;i<=n;i++) scanf("%lld",&c[i].p),q[i]=i;
scanf("%d",&k);
for (int i=1;i<=k;i++) scanf("%d%d%lld",&t[i].l,&t[i].r,&t[i].add);
t[k+1].l=1,t[k+1].r=m,t[k+1].add=1e9;
build(1,1,m);
work(1,k+1,1,n);
for (int i=1;i<=n;i++)
if (c[i].ans==k+1) printf("NIE\n");else printf("%d\n",c[i].ans);
return 0;
}
/*
6 6
1 2 3 4 5 6
10 10 10 10 10 10
3
1 3 5
4 6 6
2 4 6
*/