POI2011 流星 Meteors
阿新 • • 發佈:2019-02-27
行星 printf include 整體 pri owb () alc 發現 單位的隕石樣本。你的任務是判斷對於每個國家,在第幾次隕石雨之後,才能收集足夠的隕石。
POI2011 流星 Meteors
題目傳送門
題意
\(Byteotian\)星際聯盟,最近在附近的星系發現了一顆新的行星。盡管這顆行星由於奧妙重重的流星雨不適合人類居住,但是這給我們帶來了一個非常有趣的研究對象。
\(BIU\)的\(n\)個成員國為了采集這些隕石的樣本,將它們的空間站發射到了這顆行星的軌道附近。\(BIU\) 將這顆星球的軌道分為\(m\)份(編號從\(1\)到\(m\),且第\(m\)份和第\(1\)份相鄰),第\(i\)份上部署了第\(A_i\)個國家的太空站。
\(BIU\)已經準確地預測了接下來\(k\)場隕石雨的情況。\(BIU\)的第\(i\)個成員國希望能夠收集\(P_i\)
題解
一道整體二分裸題,第一次寫整體二分,發現也不是特別難寫,就是常數似乎大了點。
Code
#include<bits/stdc++.h> using namespace std; const int N=3e5+500; typedef long long ll; int n,nw,m,k; struct Rain { int l,r,v; }r[N]; int ans[N],P[N]; vector<int>Q,G[N]; namespace BIT { ll t[N]; int lowbit(int x) {return x&-x;} void Add(int x,int v) { for(int i=x;i<=m;i+=lowbit(i)) t[i]+=v; } ll Sum(int x) { ll ans=0; for(int i=x;i;i-=lowbit(i)) ans+=t[i]; return ans; } } void Update(int pos,int v) { if(r[pos].l<=r[pos].r) { BIT::Add(r[pos].l,v*r[pos].v);BIT::Add(r[pos].r+1,-v*r[pos].v); } else { BIT::Add(r[pos].l,v*r[pos].v);BIT::Add(m+1,-v*r[pos].v); BIT::Add(1,v*r[pos].v);BIT::Add(r[pos].r+1,-v*r[pos].v); } } void Calc(int pos) { while(nw<pos) Update(nw+1,1),nw++; while(nw>pos) Update(nw,-1),nw--; } void Solve(vector<int>Que,int l,int r) { if(!Que.size()) return ; if(l==r) { for(int i=0;i<(int)Que.size();i++) ans[Que[i]]=l; return ; } vector<int>Q1,Q2; Q1.clear();Q2.clear(); int mid=(l+r)>>1; Calc(mid); for(int i=0;i<Que.size();i++) { int o=Que[i]; ll ret=0; for(int j=0;j<(int)G[o].size();j++) { int p=G[o][j]; ret+=BIT::Sum(p); if(ret>=P[o]) break; } if(ret>=P[o]) Q1.push_back(o); else Q2.push_back(o); } Solve(Q1,l,mid); Solve(Q2,mid+1,r); } int main() { scanf("%d%d",&n,&m); for(int i=1,x;i<=m;i++) { scanf("%d",&x); G[x].push_back(i); } for(int i=1;i<=n;i++) scanf("%d",&P[i]),Q.push_back(i); scanf("%d",&k); for(int i=1;i<=k;i++) scanf("%d%d%d",&r[i].l,&r[i].r,&r[i].v); nw=0; Solve(Q,1,k+1); for(int i=1;i<=n;i++) { if(ans[i]==k+1) puts("NIE"); else printf("%d\n",ans[i]); } return 0; }
POI2011 流星 Meteors