BZOJ3343: 教主的魔法

分块
每次修改覆盖块的话就加标记
否则暴力重建

时间垫底。。。

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
#include<cstring>
using namespace std;
#define ll long long
char c;
inline void read(ll &a)
{a=0;do c=getchar();while(c<'0'||c>'9');while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();}

ll Add[4001];
ll Data[1000001];
ll Block[1000002];
ll    pl[1000002];
ll Bg[4001],Ed[4001];
ll Size,S;
ll n,i,Q,j,k,l;
ll B[4001][4001];
ll Reset(ll Blo)
{
    S+=Size;
    ll *Con=&B[Blo][0];
    *Con=0;
    for(ll i=Bg[Blo];i<=Ed[Blo];i++)
      B[Blo][++(*Con)]=Data[i];
    sort(B[Blo]+1,B[Blo]+*Con+1);
}
ll M;

inline ll Check(ll Blo)
{
    ll mid,ans=10009,l=1,r=B[Blo][0];
    while(l<=r)
      {
         mid=l+r>>1;
         if(Add[Blo]+B[Blo][mid]>=M)ans=mid,r=mid-1;
         else l=mid+1; 
      }

    if(ans==10009)return 0;
   return B[Blo][0]-ans+1;
}


int main()
{
   read(n);
   Size=sqrt(n);
   if(n>=1000) 
    Size*=6;
   Bg[Block[1]=1]=1,pl[1]=1;
   for(i=2;i<=n;i++)
    if(pl[i-1]^Size)
     {pl[i]=pl[i-1]+1,Block[i]=Block[i-1];}
    else Bg[Block[i]=Block[i-1]+1]=i,Ed[Block[i]-1]=i-1,pl[i]=1; 
   pl[i]=1;
   Ed[Block[i-1]]=i;
   read(Q);
   for(i=1;i<=n;i++)read(Data[i]); 
   for(i=1;i<=Block[n];i++)Reset(i);
   while(Q--) 
   {
    do c=getchar();while(c!='A'&&c!='M');  
    if(c=='M')
         {
           ll l,r,delta;read(l),read(r),read(delta);
           for(i=l;Block[i]==Block[l]&&i<=r;i++)Data[i]+=delta;
           if(Block[l]!=Block[r])
           for(i=r;Block[i]==Block[r]&&i>=l;i--)Data[i]+=delta;
           Reset(Block[l]); 
           if(Block[l]^Block[r])
            Reset(Block[r]);
           for(i=Block[l]+1;i<Block[r];i++)Add[i]+=delta;
         }
    else
       {
           ll l,r,ans=0;read(l),read(r),read(M); 
           for(i=l;Block[i]==Block[l]&&i<=r;i++)
                 ans+=((Data[i]+Add[Block[i]])>=M?1:0);
           if(Block[l]!=Block[r])
           for(i=r;Block[i]==Block[r]&&i>=l;i--)
                 ans+=((Data[i]+Add[Block[i]])>=M?1:0);
           for(i=Block[l]+1;i<Block[r];i++)ans+=Check(i);   
      printf("%d\n",ans);    
     }
   // printf("DeBug::%d\n",S);
   }
   return 0;

}

你可能感兴趣的:(BZOJ3343: 教主的魔法)