bzoj3343: 教主的魔法 分块 标记

修改:两边暴力重构,中间打标记。复杂度:O(n0.5)

查询:中间二分两边暴力。O(n0.5logn0.5)

总时间复杂度O(n*n0.5logn0.5)

空间复杂度是n级别的

标记不用下传因为标记不用下传也没时间下传,如果在访问时下传就造成更棘手的不整块,如果累加式下传不好记录,所以就带着就行。

细节很多......

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#define MAXN 1010000
using namespace std;
typedef long long LL;
LL a[MAXN],b[1010][1010],mark[1010],n,pos[MAXN],lon,t;
inline LL Min(LL x,LL y)
{
   return x<y?x:y;
}
int comp(const int x,const int y)
{
   return x>y;
}
inline void work1()
{
   LL l,r,w;
   scanf("%lld%lld%lld",&l,&r,&w);
   LL z=pos[l]+1,y=pos[r]-1;
   for(LL i=z;i<=y;i++)
    mark[i]+=w;
   LL zzh=(pos[l]*lon);
   zzh=Min(zzh,r);
   for(LL i=l;i<=zzh;i++) a[i]+=w;
   zzh=pos[l]*lon;
   zzh=Min(zzh,n);
   memset(b[pos[r]],0,sizeof(b[pos[r]]));
   for(LL i=zzh-lon+1;i<=zzh;i++) b[pos[l]][i%lon+1]=a[i];
   sort(b[pos[l]]+1,b[pos[l]]+lon+1);
   if(pos[l]!=pos[r])
   {
       for(LL i=(pos[r]-1)*lon+1;i<=r;i++) a[i]+=w;
       zzh=pos[r]*lon;
       zzh=Min(zzh,n);
       memset(b[pos[r]],0,sizeof(b[pos[r]]));
       for(LL i=(pos[r]-1)*lon+1;i<=zzh;i++) b[pos[r]][i%lon+1]=a[i];
       sort(b[pos[r]]+1,b[pos[r]]+lon+1);
   }
}
inline LL Count(LL p,LL c)
{
   LL ans=0,l=1,r=lon;
   while(l<=r)
   {
     LL mid=(l+r)>>1;
     if(b[p][mid]+mark[p]<c)
      l=mid+1;
     else
      ans+=(r-mid+1),r=mid-1;
   }
   return ans;
}
inline void work2()
{
   LL l,r,c,ans=0;
   scanf("%lld%lld%lld",&l,&r,&c);
   LL z=pos[l]+1,y=pos[r]-1;
   for(LL i=z;i<=y;i++)
      ans+=Count(i,c);
   LL zzh=(pos[l]*lon);
   zzh=Min(zzh,r);
   for(LL i=l;i<=zzh;i++)
     if(a[i]+mark[pos[i]]>=c)
       ans++;
   if(pos[l]!=pos[r])
   {
      for(LL i=(pos[r]-1)*lon+1;i<=r;i++)
       if(a[i]+mark[pos[i]]>=c)
         ans++;
   }
   printf("%lld\n",ans);
}
int main()
{
   scanf("%lld",&n);
   LL Q;
   scanf("%lld",&Q);
   lon=(LL)sqrt(n+0.5);
   for(LL i=1;i<=n;i++)
   {
      scanf("%lld",&a[i]);
      pos[i]=(i-1)/lon+1;
      b[pos[i]][i%lon+1]=a[i];
   }
   t=pos[n];
   for(int i=1;i<=t;i++)
    sort(b[i]+1,b[i]+lon+1);
   while(Q--)
   {
     char s[2];
     scanf("%s",s);
     if(s[0]=='M')work1();
     else work2();
   }
   return 0;
}

 

posted @ 2017-06-14 11:01  TS_Hugh  阅读(216)  评论(0编辑  收藏  举报