P3527 [POI2011]MET-Meteors
题意翻译
( t{Byteotian Interstellar Union})有(N)个成员国。现在它发现了一颗新的星球,这颗星球的轨道被分为(M)份(第(M)份和第(1)份相邻),第(i)份上有第(A_i)个国家的太空站。 这个星球经常会下陨石雨。( t{BIU})已经预测了接下来(K)场陨石雨的情况。 ( t{BIU})的第(i)个成员国希望能够收集(P_i)单位的陨石样本。你的任务是判断对于每个国家,它需要在第几次陨石雨之后,才能收集足够的陨石。
输入
第一行是两个数(N),(M)。 第二行有(M)个数,第(i)个数(O_i)表示第(i)段轨道上有第(O_i)个国家的太空站。 第三行有(N)个数,第(i)个数(P_i)表示第(i)个国家希望收集的陨石数量。 第四行有一个数(K),表示( t{BIU})预测了接下来的(K)场陨石雨。 接下来(K)行,每行有三个数(L_i,R_i,A_i),表示第(K)场陨石雨的发生地点在从(L_i)顺时针到(R_i)的区间中(如果(L_i le R_i),就是(L_i,L_{i+1},dots,R_i),否则就是(R_i,R_{i+1},dots,m-1,m,1,dots,L_i)),向区间中的每个太空站提供(A_i)单位的陨石样本。
输出
(N)行。第(i)行的数(W_i)表示第(i)个国家在第(W_i)波陨石雨之后能够收集到足够的陨石样本。如果到第(K)波结束后仍然收集不到,输出(NIE)。
数据范围:
(1le n,m,kle 3 imes 10^5,1le Pile 10^9,1le Ai<10^9)
整体二分,按时间二分陨石雨,划分一下国家。树状数组维护区间加单点查就行。
注意可能爆( t{long long}),边读边看多没多
Code:
// luogu-judger-enable-o2
#include <cstdio>
#include <vector>
#include <cctype>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;i++)
const int N=3e5+10;
ll read()
{
ll x=0;char c=getchar();
while(!isdigit(c)) c=getchar();
while(isdigit(c)){x=x*10+c-'0';c=getchar();}
return x;
}
struct Q{int k,id;std::vector <int> pos;}q[N],ql[N],qr[N];;
struct node{int l,r;ll a;}op[N];
ll s[N];int ans[N],n,m,k;
void add(int x,ll d){while(x<=m)s[x]+=d,x+=x&-x;}
ll query(int x){ll sum=0;while(x)sum+=s[x],x-=x&-x;return sum;}
void divide(int l,int r,int s,int t)
{
if(s>t) return;
if(l==r){rep(i,s,t)ans[q[i].id]=l;return;}
int mid=l+r>>1,lp=0,rp=0;
rep(i,l,mid)
{
if(op[i].l<=op[i].r) add(op[i].l,op[i].a),add(op[i].r+1,-op[i].a);
else add(1,op[i].a),add(op[i].r+1,-op[i].a),add(op[i].l,op[i].a);
}
rep(i,s,t)
{
ll c=0;
for(int j=0;j<q[i].pos.size();j++)
{
c+=query(q[i].pos[j]);
if(q[i].k<=c) {ql[++lp]=q[i];break;}
}
if(q[i].k>c)qr[++rp]=q[i],qr[rp].k-=(int)(c);
}
rep(i,l,mid)
{
if(op[i].l<=op[i].r) add(op[i].l,-op[i].a),add(op[i].r+1,op[i].a);
else add(1,-op[i].a),add(op[i].r+1,op[i].a),add(op[i].l,-op[i].a);
}
rep(i,s,s+lp-1) q[i]=ql[i+1-s];
rep(i,s+lp,t) q[i]=qr[i+1-s-lp];
divide(l,mid,s,s+lp-1),divide(mid+1,r,s+lp,t);
}
int main()
{
n=read(),m=read();
rep(i,1,m) q[read()].pos.push_back(i);
rep(i,1,n) q[i].k=read(),q[i].id=i;
k=read();
rep(i,1,k) op[i].l=read(),op[i].r=read(),op[i].a=read();
op[++k]={1,1,0};
divide(1,k,1,n);
rep(i,1,n)
{
if(ans[i]==k) puts("NIE");
else printf("%d
",ans[i]);
}
return 0;
}
2018.11.3