1. 程式人生 > >BZOJ2527 & 洛谷3527:[Poi2011]Meteors——題解

BZOJ2527 & 洛谷3527:[Poi2011]Meteors——題解

tps 我的博客 ace printf show tro bzoj2527 quest new

+++++++++++++++++++++++++++++++++++++++++++

+本文作者:luyouqi233。               +

+歡迎訪問我的博客:http://www.cnblogs.com/luyouqi233/+

+++++++++++++++++++++++++++++++++++++++++++

https://www.luogu.org/problemnew/show/3527

http://www.lydsy.com/JudgeOnline/problem.php?id=2527

(事先說明,本人是開O2過的洛谷,如果不開的話請用數組模擬STL)

(代碼和題解參考洛谷的題解第一篇)

(采用BZOJ翻譯)

Byteotian Interstellar Union有N個成員國。現在它發現了一顆新的星球,這顆星球的軌道被分為M份(第M份和第1份相鄰),第i份上有第Ai個國家的太空站。這個星球經常會下隕石雨。 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

顯然是一道維護區間的題,如果不考慮用什麽奇葩難寫的數據結構的話,還是整體二分+樹狀數組好些。

……但是一旦會了整體二分之後不就是水題了嗎……

我們二分每個成員國最少需要多少波操作會到達他們的預定值,剩下的就是套路了。

不過需要註意這題可能爆longlong,開longlong的同時記的判斷並及時跳出。

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1000055;
inline ll read(){
    ll X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==-;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct question{
    int l,r,op,id;
    ll k;
}q[N],tmp1[N],tmp2[N];
vector<int>g[N];
int ans[N],aim[N];
ll tree[N];
int n,m,p;
inline int lowbit(int t){return t&(-t);}
inline void add(int x,ll y){//將a[x]+y
    for(int i=x;i<=m;i+=lowbit(i))tree[i]+=y;
}
inline ll query(int x){//1-x區間和
    ll res=0;
    for(int i=x;i>0;i-=lowbit(i))res+=tree[i];
    return res;
}
inline void modify(ll x,ll y,ll z){
    add(x,z);add(y+1,-z);
}
void solve(int L,int R,int l,int r){
    if(L>R)return;
    if(l==r){
        for(int i=L;i<=R;i++){
            if(q[i].op==1)ans[q[i].id]=l;
        }
        return;
    }
    int idx1=0,idx2=0,mid=(l+r)>>1;
    for(int i=L;i<=R;i++){
        if(q[i].op==1){
            ll tmp=0;
            for(int j=0;j<g[q[i].id].size();j++){
                tmp+=query(g[q[i].id][j]);
                if(tmp>q[i].k)break;
            }
            if(tmp>=q[i].k)tmp1[idx1++]=q[i];
            else{q[i].k-=tmp;tmp2[idx2++]=q[i];}
        }else{
            if(q[i].id<=mid){
                if(q[i].op==2)modify(q[i].l,q[i].r,q[i].k);
                else modify(q[i].l,m,q[i].k),modify(1,q[i].r,q[i].k);
                tmp1[idx1++]=q[i];
            }else tmp2[idx2++]=q[i];
        }
    }
    for(int i=0;i<idx1;i++){
        question k=tmp1[i];
        if(k.op==2)modify(k.l,k.r,-k.k);
        else if(k.op==3)modify(k.l,m,-k.k),modify(1,k.r,-k.k);
    }
    bool ok1=0,ok2=0;
    int MID=L+idx1;
    for(int i=L;i<MID;i++)q[i]=tmp1[i-L],ok1=1;
    for(int i=MID;i<=R;i++)q[i]=tmp2[i-MID],ok2=1;
    if(ok1)solve(L,MID-1,l,mid);
    if(ok2)solve(MID,R,mid+1,r);
    return;
}
int main(){
    n=read(),m=read();
    for(int i=1;i<=m;i++)g[read()].push_back(i);
    for(int i=1;i<=n;i++)aim[i]=read();
    p=read();
    for(int i=1;i<=p;i++){
        q[i].l=read();q[i].r=read();q[i].k=read();
        if(q[i].r>=q[i].l)q[i].op=2;
        else q[i].op=3;
        q[i].id=i;
    }
    for(int i=1;i<=n;i++){
        q[i+p].k=aim[i];q[i+p].op=1;q[i+p].id=i;
    }
    solve(1,n+p,1,p+1);
    for(int i=1;i<=n;i++){
        if(ans[i]!=p+1)printf("%d\n",ans[i]);
        else puts("NIE");
    }
    return 0;
}

BZOJ2527 & 洛谷3527:[Poi2011]Meteors——題解