bzoj2527[Poi2011]Meteors 整體二分

 

題目描述:

這個星球經常會下隕石雨。BIU已經預測了接下來K場隕石雨的情況。 BIU的第i個成員國希望能夠收集Pi單位的隕石樣本。你的任務是判斷對於每個國家,它需要在第幾次隕石雨之後,才能收集足夠的隕石。 輸入: 第一行是兩個數N,M。 第二行有M個數,第i個數Oi表示第i段軌道上有第Oi個國家的太空站。 第三行有N個數,第i個數Pi表示第i個國家希望收集的隕石數量。 第四行有一個數K,表示BIU預測了接下來的K場隕石雨。 接下來K行,每行有三個數Li,Ri,Ai,表示第K場隕石雨的發生地點在從Li順時針到Ri的區間中(如果Li<=Ri,就是Li,Li+1,...,Ri,否則就是Ri,Ri+1,...,m-1,m,1,...,Li),向區間中的每個太空站提供Ai單位的隕石樣本。 輸出: N行。第i行的數Wi表示第i個國家在第Wi波隕石雨之後能夠收集到足夠的隕石樣本。如果到第K波結束後仍然收集不到,輸出NIE。
數據範圍: 1<=n,m,k<=3*10^5 1<=Pi<=10^9 1<=Ai<10^9

 

Sample Input

3 5
1 3 2 1 3
10 5 7
3
4 2 4
1 3 1
3 5 2

Sample Output

3
NIE
1

據說這道題可以用斐波那契數列+二分過,

但我菜到只會用整體二分,請求原諒QWQ......

上代碼:

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define int long long
using namespace std;
const int maxn=300005;
int c[maxn];
int ans[maxn];
int n,m,Q,x,now;
vector<int>to[maxn];
struct query{int l,r,val;}q[maxn];
struct node{int id,k;}a[maxn],tmp[maxn];
inline int lowbit(int x){return x&-x;}
inline void add(int u,int v)
{
    for(int i=u;i<=m;i+=lowbit(i))
      c[i]+=v;
}
inline int getsum(int u)
{
    int sum=0;
    for(int i=u;i>=1;i-=lowbit(i))
      sum+=c[i];
    return sum;
}
inline void Add(int l,int r,int v)
{
    if(l<=r) add(l,v),add(r+1,-v);
    else add(l,v),add(1,v),add(r+1,-v);
}
inline void CDQ(int L,int R,int l,int r)//別看他叫CDQ,那他也是整體二分。
{
    int l1=L,l2=R,mid=(l+r>>1);
    if(l==r)
    {
        fo(i,L,R) ans[a[i].id]=l;
        return;
    }
    while(now<=mid) now++,Add(q[now].l,q[now].r,q[now].val);
    while(now>mid) Add(q[now].l,q[now].r,-q[now].val),now--;
//  fo(i,1,mid) Add(q[i].l,q[i].r,q[i].val);
    fo(i,L,R)
    {
        int sum=0;
        for(int j=0;j<to[a[i].id].size();j++)
        {
            int czy=to[a[i].id][j];
            sum+=getsum(czy);
            if(sum>=a[i].k) break;
        }
        if(sum>=a[i].k) tmp[l1++]=a[i];
        else tmp[l2--]=a[i];
    }
    reverse(tmp+l2+1,tmp+R+1);
    fo(i,L,R) a[i]=tmp[i];
//  fo(i,1,mid) Add(q[i].l,q[i].r,-q[i].val);
    CDQ(L,l1-1,l,mid);
    CDQ(l2+1,R,mid+1,r);
}
signed main()
{
    scanf("%lld%lld",&n,&m);
    fo(i,1,m)
    {
        scanf("%lld",&x);
        to[x].push_back(i);
    }
    fo(i,1,n) a[i].id=i,scanf("%lld",&a[i].k);scanf("%lld",&Q);
    fo(i,1,Q) scanf("%lld%lld%lld",&q[i].l,&q[i].r,&q[i].val);
    Q++,q[Q].l=1,q[Q].r=m,q[Q].val=1e9+7;
    CDQ(1,n,1,Q);
    fo(i,1,n)
      if(ans[i]<Q) printf("%lld\n",ans[i]);
      else puts("NIE");
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章