2527:[Poi2011]Meteors
时间限制: 2000 ms 内存限制: 131072 KB
题目描述
Byteotian Interstellar Union有 N N 个成员国。现在它发现了一颗新的星球,这颗星球的轨道被分为份(第 M M 份和第1份相邻),第份上有第 Ai A i 个国家的太空站。
这个星球经常会下陨石雨。BIU已经预测了接下来 K K 场陨石雨的情况。
BIU的第个成员国希望能够收集 Pi P i 单位的陨石样本。你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石。
输入:
第一行是两个数
N,M
N
,
M
。
第二行有
M
M
个数,第个数
Oi
O
i
表示第i段轨道上有第
Oi
O
i
个国家的太空站。
第三行有
N
N
个数,第个数
Pi
P
i
表示第
i
i
个国家希望收集的陨石数量。
第四行有一个数,表示BIU预测了接下来的
K
K
场陨石雨。
接下来行,每行有三个数 Li,Ri,Ai L i , R i , A i ,表示第 K K 场陨石雨的发生地点在从顺时针到 Ri R i 的区间中(如果 Li≤Ri L i ≤ R i ,就是 Li L i , Li+1 L i + 1 ,…, Ri R i ,否则就是 Ri R i , Ri+1 R i + 1 ,…, m−1 m − 1 , m m ,1,…,),向区间中的每个太空站提供 Ai A i 单位的陨石样本。
输出:
N N 行。第行的数 Wi W i 表示第 i i 个国家在第波陨石雨之后能够收集到足够的陨石样本。如果到第 K K 波结束后仍然收集不到,输出NIE。
数据范围:
1≤Pi≤109
1
≤
P
i
≤
10
9
1≤Ai<109
1
≤
A
i
<
10
9
输入样例
3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2
输出样例
3
NIE
1
解:
首先想到用链表存一下每个国家收集点的位置,然后就还是按照时间二分,主要判一下无解的情况。而且比较坑的是,如果一个国家收集点很多,收集的陨石可能会爆
longlong
l
o
n
g
l
o
n
g
,要及时break。
code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define lowbit(x) ((x)&(-x))
using namespace std;
struct data{
int l,r;
long long a;
}q[300005];
struct lxy1{
int id,next;
}eg[3000005];
queue <int> d1,d2;
int n,m,k,cnt,root;
int cty[300005],ans[300005],head[300005];
long long aim[300005];
long long b[300005];
int readit()
{
int a=0;char s;
s=getchar();
while(s<'0'||s>'9') s=getchar();
while(s>='0'&&s<='9')
{
a=a*10+s-'0';
s=getchar();
}
return a;
}
void add(int op,int ed)
{
eg[++cnt].next=head[op];
eg[cnt].id=ed;
head[op]=cnt;
}
void modify(int u,long long x)
{
while(u<=m){
b[u]+=x;
u+=lowbit(u);
}
}
long long query(int u)
{
long long ret=0;
while(u>0){
ret+=b[u];
u-=lowbit(u);
}
return ret;
}
void cdq(int ml,int mr,int ql,int qr)
{
int midm=(ml+mr)>>1;
if(ml==mr&&ml!=k)
{
for(int i=ql;i<=qr;i++)
ans[cty[i]]=ml;
return;
}
for(int i=ml;i<=midm;i++)
{
if(q[i].l<=q[i].r) modify(q[i].l,q[i].a),modify(q[i].r+1,-q[i].a);
else modify(q[i].l,q[i].a),modify(1,q[i].a),modify(q[i].r+1,-q[i].a);
}
int gg=ql-1,mid;
for(int i=ql;i<=qr;i++)
{
long long s=0;
for(int j=head[cty[i]];j!=-1;j=eg[j].next){
s+=query(eg[j].id);
if(s>=aim[cty[i]]) break;
}
if(s<aim[cty[i]]&&ml==k){
ans[cty[i]]=-1;
}
else if(s>=aim[cty[i]]) d1.push(cty[i]);
else if(s<aim[cty[i]]) d2.push(cty[i]),aim[cty[i]]-=s;
}
if(ml==k) {
while(!d1.empty())
ans[d1.front()]=ml,d1.pop();
while(!d2.empty())
ans[d2.front()]=ml,d2.pop();
return;
}
while(!d1.empty())
cty[++gg]=d1.front(),d1.pop();
mid=gg;
while(!d2.empty())
cty[++gg]=d2.front(),d2.pop();
for(int i=ml;i<=midm;i++)
{
if(q[i].l<=q[i].r) modify(q[i].l,-q[i].a),modify(q[i].r+1,q[i].a);
else modify(q[i].l,-q[i].a),modify(1,-q[i].a),modify(q[i].r+1,q[i].a);
}
if(mid>=ql) cdq(ml,midm,ql,mid);
if(mid<gg) cdq(midm+1,mr,mid+1,gg);
}
int main()
{
memset(head,-1,sizeof(head));
n=readit();m=readit();
for(int i=1;i<=m;i++)
cty[i]=readit(),add(cty[i],i);
for(int i=1;i<=n;i++)
aim[i]=readit();
cnt=0;int t=1;
while(aim[t]!=0&&t<=n)
cty[++cnt]=t,t++;
k=readit();
for(int i=1;i<=k;i++)
q[i].l=readit(),q[i].r=readit(),q[i].a=readit();
cdq(1,k,1,cnt);
for(int i=1;i<=n;i++){
if(ans[i]==-1) printf("NIE\n");
else printf("%d\n",ans[i]);
}
}