1. 程式人生 > >[BOI2011]MET-Meteors

[BOI2011]MET-Meteors

struct fin 題目 return 空間站 stars 分開 復雜度 push_back

題目:洛谷P3527。

題目大意:
n個國家在某星球上建立了m個空間站(一個空間站只屬於一個國家),空間站圍成一個環。
現在知道要下k天隕石,每天都在一個區間內下,每個點都下同樣多的(若r>l,則說明區間是\(1~r和l~m\))。
每個國家有一個目標隕石數。
問每個國家最早在什麽時候達到目標隕石數。若下完了還達不到,則輸出NIE。
解題思路:
整體二分。
對所有的國家一起二分,用樹狀數組維護前綴(後綴)。
對於每個答案,將能達到目標的國家和達不到的國家分開,然後繼續二分即可。
時間復雜度\(O(n\log^2 n)\)。

線段樹被卡常┭┮﹏┭┮

C++ Code:

#include<cstdio>
#include<vector>
#include<cctype>
#define LoveLive long long
const int M=500005,N=300005;
int k,n,m,P[N],q[N],ans[N],now,tmp[N];std::vector<int>a[N];
LoveLive Bit[M];
bool type[N];
inline int readint(){
    int c=getchar(),d=0;
    for(;!isdigit(c);c=getchar());
    for(;isdigit(c);c=getchar())
    d=(d<<3)+(d<<1)+(c^‘0‘);
    return d;
}
struct stars{
    int l,r,s;
}d[N];
inline void add(int i,int a){for(;i<=m;i+=i&-i)Bit[i]+=a;}
inline LoveLive query(int i){LoveLive a=0;for(;i;i-=i&-i)a+=Bit[i];return a;}
inline void update(int tm,int det){
    if(d[tm].l<=d[tm].r)add(d[tm].l,det*d[tm].s),add(d[tm].r+1,-det*d[tm].s);else
    add(1,det*d[tm].s),add(d[tm].r+1,-det*d[tm].s),add(d[tm].l,det*d[tm].s);
}
void solve(int l,int r,int l1,int l2){
    if(l1>l2)return;
    if(l==r){
        for(int i=l1;i<=l2;++i)ans[q[i]]=l;
        return;
    }
    int mid=l+r>>1;
    while(now<mid)update(++now,1);
    while(now>mid)update(now--,-1);
    int cnt=0;
    for(int i=l1;i<=l2;++i){
        LoveLive p=0;
        int&id=q[i];
        for(int j=0,dd=a[id].size();j<dd&&p<P[id];++j)p+=query(a[id][j]);
        if(p>=P[id])type[id]=1,++cnt;else
        type[id]=0;
    }
    int t1=l1,t2=l1+cnt;
    for(int i=l1;i<=l2;++i)
    if(type[q[i]])tmp[t1++]=q[i];else
    tmp[t2++]=q[i];
    for(int i=l1;i<=l2;++i)q[i]=tmp[i];
    solve(l,mid,l1,t1-1);
    solve(mid+1,r,t1,l2);
}
int main(){
    n=readint(),m=readint();
    for(int i=1;i<=m;++i)a[readint()].push_back(i);
    for(int i=1;i<=n;++i)P[q[i]=i]=readint();
    k=readint()+1;
    for(int i=1;i<k;++i){
        d[i].l=readint();
        d[i].r=readint();
        d[i].s=readint();
    }
    d[k]=(stars){1,m,1e9};
    solve(1,k,1,n);
    for(int i=1;i<=n;++i)
    if(ans[i]<k)printf("%d\n",ans[i]);else puts("NIE");
    return 0;
}

[BOI2011]MET-Meteors