BZOJ 2527: [Poi2011]Meteors

Description

\(n\)个国家一共有\(m\)个收集器,每次会在一个范围内落下\(a_i\)个物品,每个国家有收集目标,问每个国家至少多少次可以收集完.\(n,m,k \leqslant 3\times 10^5\)

Solution

整体二分.

二分答案的同时将询问分类,分成小于等于\(mid\),和大于\(mid\),递归操作.

用树状数组差分可以得到单点的权值,因为每层只会进行\(n\)次操作,一共\(logn\)层,所以总复杂度应该是\(O(nlog^2n)\)

Code

/**************************************************************
    Problem: 2527
    User: BeiYu
    Language: C++
    Result: Accepted
    Time:22716 ms
    Memory:21396 kb
****************************************************************/
 
#include <bits/stdc++.h>
using namespace std;
 
#define debug(a) cout<<#a<<"="<<a<<" "
#define mid ((l+r)>>1)
 
typedef long long LL;
typedef pair< int,int > pr;
const int N = 3e5+50;
const int INF = 1e9+7;
 
inline int in(int x=0,char ch=getchar()) { while(ch>'9' || ch<'0') ch=getchar();
    while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();return x; }
 
int n,m,k;
int a[N],tar[N],t1[N],t2[N],tt[N],ans[N];
vector< int > g[N];
struct Q { int l,r,a; } qr[N];
 
LL d[N];
void Add(int x,LL v) { for(;x<=m;x+=x&-x) d[x]+=v; }
LL Sum(int x,LL r=0) { for(;x;x-=x&-x) r+=d[x];return r; }
 
void Solve(int l,int r,int L,int R) {
//  debug(l),debug(r),debug(L),debug(R)<<endl;
//  for(int i=L;i<=R;i++) cout<<a[i]<<" ";cout<<endl;
//  cout<<"----------------------------------------"<<endl;
     
     
    if(l==r) {
        for(int i=L;i<=R;i++) ans[a[i]]=l;
        return;
    }
//  if(l==1 && r==k) for(int i=1;i<=m;i++) cout<<Sum(i)<<endl;
    for(int i=l;i<=mid;i++) {
        if(qr[i].l<=qr[i].r) Add(qr[i].l,qr[i].a),Add(qr[i].r+1,-qr[i].a);
        else Add(1,qr[i].a),Add(qr[i].r+1,-qr[i].a),Add(qr[i].l,qr[i].a);
    }
//  if(l==1 && r==k) for(int i=1;i<=m;i++) cout<<Sum(i)<<endl;
    int c1,c2;c1=c2=0;
    for(int i=L;i<=R;i++) {
        LL tmp=0;
        for(int j=0;j<(int)g[a[i]].size();j++) { tmp+=Sum(g[a[i]][j]);if(tmp>=tar[a[i]]) break; }
        if(tmp>=tar[a[i]]) t1[++c1]=a[i];
        else t2[++c2]=a[i];
//      cout<<a[i]<<" "<<tmp<<endl;
    }
//  debug(c1),debug(c2)<<endl;
//  cout<<"----------------------------------------"<<endl;
    for(int i=1;i<=c2;i++) a[L+c1+i-1]=t2[i];
    for(int i=1;i<=c1;i++) a[L+i-1]=t1[i];
    Solve(mid+1,r,L+c1,R);
     
    for(int i=l;i<=mid;i++) {
        if(qr[i].l<=qr[i].r) Add(qr[i].l,-qr[i].a),Add(qr[i].r+1,qr[i].a);
        else Add(1,-qr[i].a),Add(qr[i].r+1,qr[i].a),Add(qr[i].l,-qr[i].a);
    }
    Solve(l,mid,L,L+c1-1);
}
 
int main() {
//  freopen("in.in","r",stdin);
    n=in(),m=in();
    for(int i=1,x;i<=m;i++) x=in(),g[x].push_back(i);
    for(int i=1;i<=n;i++) tar[i]=in(),a[i]=i;
    k=in();
    for(int i=1;i<=k;i++) {
        int ll=in(),rr=in(),aa=in();
        qr[i]=(Q){ ll,rr,aa };
    }
    qr[++k]=(Q){ 1,m,INF };
    Solve(1,k,1,n);
    for(int i=1;i<=n;i++) (ans[i]==k)?puts("NIE"):printf("%d\n",ans[i]);
    return 0;
}
/*
3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2
*/

 

posted @ 2017-01-21 20:47  北北北北屿  阅读(161)  评论(0编辑  收藏  举报