[分块] BZOJ 2122 工作评估

来源:互联网 发布:褪黑素 知乎 编辑:程序博客网 时间:2024/06/10 03:09

比较好的一道分块题

重要结论F(i,j,x0)=min( G(i,j), x0+S(i,j))

详见:http://blog.csdn.net/u011542204/article/details/51504804


#include<cstdio>#include<cstdlib>#include<algorithm>#include<vector>#include<cmath>#define dprintf(...) fprintf(stderr,__VA_ARGS__) using namespace std;typedef pair<int,int> abcd;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  if (p1==p2){ p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }  return *p1++;}inline void read(int &x){  char c=nc(),b=1;  for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;  for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}void pp(vector<abcd> &vec){  for (int i=0;i<(signed)vec.size();i++)    dprintf("%d %d\n",vec[i].first,vec[i].second);  dprintf("\n");}const int N=50005;const int Bo=225;int n,D[N],L[N],sD[N];int B,pos[N];int cnt,llim[Bo],rlim[Bo];vector<abcd> Vec[Bo],pre[Bo],suf[Bo];int F[Bo][Bo][Bo];inline int S(int l,int r){  return F[pos[l]][l-llim[pos[l]]][r-llim[pos[l]]];}inline int G(int l,int r){  return sD[r]-sD[l-1];}abcd T[N]; int tcnt;int Stk[N],pnt;inline void Calc(vector<abcd> &vec){  sort(T+1,T+tcnt+1);  pnt=0;  for (int i=1;i<=tcnt;i++){    while (pnt && T[i].second>=T[Stk[pnt]].second) pnt--;    Stk[++pnt]=i;  }  for (int i=1;i<=pnt;i++)    vec.push_back(T[Stk[i]]);}inline void Init(int pos,int l,int r){  for (int i=l;i<=r;i++){    int x0=1<<30;    for (int j=i;j<=r;j++)      x0=min(x0+D[j],L[j]),F[pos][i-l][j-l]=x0;  }  tcnt=0;  for (int i=l;i<=r;i++)    for (int j=i;j<=r;j++)      T[++tcnt]=abcd(S(i,j),G(i,j));  Calc(Vec[pos]);  tcnt=0;  for (int i=l;i<=r;i++)    T[++tcnt]=abcd(S(l,i),G(l,i));  Calc(pre[pos]);  tcnt=0;  for (int i=l;i<=r;i++)    T[++tcnt]=abcd(S(i,r),G(i,r));  Calc(suf[pos]);}inline int Query(vector<abcd> &vec,int x0){  int L=0,R=vec.size(),MID;  while (L+1<R){    MID=(L+R)>>1;    if (vec[MID].first>vec[MID].second+x0)      R=MID;    else      L=MID;  }  int ret=min(vec[L].first,vec[L].second+x0);  if (L+1<vec.size())    ret=max(ret,min(vec[L+1].first,vec[L+1].second+x0));  return ret;}inline void Solve(int l,int r,int x0){  int lp=pos[l],rp=pos[r],Y,tmp;  int ans=x0;  if (lp==rp){    Y=x0;    for (int i=l;i<=r;i++)      Y=min(max(Y,x0)+D[i],L[i]),ans=max(ans,Y);    printf("%d\n",ans);    return;  }  Y=x0;  for (int i=l;i<=rlim[lp];i++)      Y=min(max(Y,x0)+D[i],L[i]),ans=max(ans,Y);  Y=max(Y,x0);    for (int i=lp+1;i<rp;i++){    tmp=Query(pre[i],Y);    ans=max(ans,tmp);    tmp=Query(Vec[i],x0);    ans=max(ans,tmp);    Y=min(G(llim[i],rlim[i])+Y,S(llim[i],rlim[i]));      tmp=Query(suf[i],x0);      Y=max(Y,tmp);    Y=max(Y,x0);    }  for (int i=llim[rp];i<=r;i++)      Y=min(max(x0,Y)+D[i],L[i]),ans=max(ans,Y);    printf("%d\n",ans);}int main(){  int Q; int l,r,x0;  freopen("t.in","r",stdin);  freopen("t.out","w",stdout);  read(n); read(Q);  for (int i=1;i<=n;i++) read(D[i]),sD[i]=sD[i-1]+D[i];  for (int i=1;i<=n;i++) read(L[i]);  B=sqrt(n);  for (int i=1;i<=n;i++) pos[i]=(i-1)/B+1;  cnt=pos[n];  for (int i=1;i<=cnt;i++) llim[i]=(i-1)*B+1,rlim[i]=i*B;  rlim[cnt]=n;  for (int i=1;i<=cnt;i++)    Init(i,llim[i],rlim[i]);  while (Q--){    read(l); read(r); read(x0);    Solve(l,r,x0);  }  return 0;}


0 0
原创粉丝点击