http://www.spoj.com/problems/METEORS/ (题目链接)
题意
一个星球上有$m$个空间站排列在一个环形轨道上,每个空间站仅属于一个国家。总共有$K$场流星雨,这些流星雨降落在区间$[l,r]$的空间站并带来$w$的陨石。每个国家想要收获$p_i$的陨石,问每个国家最少在第几场流星雨过后收集到的陨石达到要求。
Solution
整体二分很明显,一开始复杂度算错了T_T。
细节
本机7s,SPOJ竟然跑过去了w(゚Д゚)w。听说会爆LL
代码
// spojMETEORS
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#define LL long long
#define ULL unsigned long long
#define inf 2147483600
#define Pi acos(-1.0)
#define free(a) freopen(a".in","r",stdin),freopen(a".out","w",stdout)
using namespace std;
inline int gi() {
int x=0,f=1;char ch=getchar();
while (ch<'0' || ch>'9') {if (ch=='-') f=-1;ch=getchar();}
while (ch>='0' && ch<='9') {x=x*10+ch-'0';ch=getchar();}
return x*f;
}
const int maxn=300010;
int n,m,K,cnt,a[maxn],ans[maxn],head[maxn];
struct edge {int to,next;}e[maxn];
struct data {int w,id;}p[maxn],lp[maxn],rp[maxn];
struct node {int l,r;ULL s,tag;}tr[maxn<<2];
struct mete {int l,r,w;}q[maxn];
namespace Segtree {
void build(int k,int s,int t) {
tr[k].l=s;tr[k].r=t;
if (s==t) return;
int mid=(s+t)>>1;
build(k<<1,s,mid);
build(k<<1|1,mid+1,t);
}
void modify(int k,int s,int t,LL val) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==s && r==t) {tr[k].s+=val*(r-l+1);tr[k].tag+=val;return;}
if (t<=mid) modify(k<<1,s,t,val);
else if (s>mid) modify(k<<1|1,s,t,val);
else modify(k<<1,s,mid,val),modify(k<<1|1,mid+1,t,val);
tr[k].s=tr[k<<1].s+tr[k<<1|1].s;
}
ULL query(int k,int p) {
int l=tr[k].l,r=tr[k].r,mid=(l+r)>>1;
if (l==r) return tr[k].s;
if (p<=mid) return query(k<<1,p)+tr[k].tag;
else return query(k<<1|1,p)+tr[k].tag;
}
}
using namespace Segtree;
void link(int u,int v) {
e[++cnt]=(edge){v,head[u]};head[u]=cnt;
}
void solve(int ql,int qr,int l,int r) {
if (ql>qr) return;
int mid=(ql+qr)>>1,l1=0,l2=0;
for (int i=ql;i<=mid;i++) {
if (q[i].l>q[i].r) modify(1,q[i].l,m,q[i].w),modify(1,1,q[i].r,q[i].w);
else modify(1,q[i].l,q[i].r,q[i].w);
}
for (int i=l;i<=r;i++) {
ULL sum=0;
for (int j=head[p[i].id];j;j=e[j].next) sum+=query(1,e[j].to);
if (p[i].w<=sum) lp[++l1]=p[i],ans[p[i].id]=mid;
else rp[++l2]=p[i];
}
for (int i=1;i<=l1;i++) p[l+i-1]=lp[i];
for (int i=1;i<=l2;i++) p[r-i+1]=rp[i];
if (l+l1<=r) solve(mid+1,qr,l+l1,r);
for (int i=ql;i<=mid;i++) {
if (q[i].l>q[i].r) modify(1,q[i].l,m,-q[i].w),modify(1,1,q[i].r,-q[i].w);
else modify(1,q[i].l,q[i].r,-q[i].w);
}
if (l<=r-l2) solve(ql,mid-1,l,r-l2);
}
int main() {
n=gi(),m=gi();
for (int i=1;i<=m;i++) a[i]=gi();
for (int i=1;i<=m;i++) link(a[i],i);
for (int i=1;i<=n;i++) p[i].w=gi(),p[i].id=i;
K=gi();
for (int i=1;i<=K;i++) q[i].l=gi(),q[i].r=gi(),q[i].w=gi();
build(1,1,m);
solve(1,K,1,n);
for (int i=1;i<=n;i++) {
if (!ans[i]) puts("NIE");
else printf("%d\n",ans[i]);
}
return 0;
}