[BOI2011]MET-Meteors
阿新 • • 發佈:2018-07-10
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