洛谷P2801 教主的魔法

询问区间内有多少数大于等于x,并且支持区间修改

发现线段树做不了

树状数组也不行

原来是分块!

分块是一种优雅的暴力,把长度为n的区间分成sqrt(n)块,每块长度为sqrt(n)

如果不是整的多出几个也没关系

原则是完整的块数直接求,零散的再暴力

比如要查询 1 2 3 4 5 6 7 8 9 10中的2-9

每块长度为3,那么可拆分为第一块的2、3,第二块和第三块;

 

那么对于此题,区间修改可以用tag优化(就是线段树那个tag)

其他的就是把板子熟悉一下>_<

 

复制代码
#include<bits/stdc++.h>
using namespace std;
int len,n,q;
const int maxn=3007;
vector<int>v[maxn];
int tag[maxn],belong[int(1e6)+7],h[int(1e6)+7];
void reset(int x)
{
    v[x].clear();
    for(int i=(x-1)*len+1;i<=min(x*len,n);i++)
     {
         v[x].push_back(h[i]);
     }
    sort(v[x].begin(),v[x].end());
}
void add(int l,int r,int t)
{
    for(int i=l;i<=min(r,belong[l]*len);i++)
     {
         h[i]+=t;
     }
     reset(belong[l]);
    
         for(int i=belong[l]+1;i<=belong[r]-1;i++)
          tag[i]+=t;
     
     if(belong[l]!=belong[r])
     {
     for(int i=(belong[r]-1)*len+1;i<=r;i++)
      {
          h[i]+=t;
      }
     reset(belong[r]);
     }
}
int query(int l,int r,int t)
{
    int ans=0;
    for(int i=l;i<=min(r,belong[l]*len);i++)
     {
         if(h[i]+tag[belong[i]]<t) 
         {
             ans++; 
         }
     }
     if(belong[l]!=belong[r])
     {
         for(int i=(belong[r]-1)*len+1;i<=r;i++)
      { 
         if(h[i]+tag[belong[r]]<t) 
         {
             ans++;
         } 
      }
     }
     
     for(int i=belong[l]+1;i<=belong[r]-1;i++)
          {
            int id=lower_bound(v[i].begin(),v[i].end(),t-tag[i])-v[i].begin();
           ans+=id;    

         }
     return r-l+1-ans;
}
int main()
{
    cin>>n>>q;
    len=sqrt(n);
    for(int i=1;i<=n;i++) 
    {
        scanf("%d",&h[i]);
        int id=(i-1)/len+1;
        belong[i]=id;
        v[id].push_back(h[i]);
    }
    for(int i=1;i<=belong[n];i++) sort(v[i].begin(),v[i].end());
    for(int i=1;i<=q;i++)
    {
        char f;
        cin>>f;
        int l,r,t;
        scanf("%d%d%d",&l,&r,&t);
        if(f=='M')
        {
          add(l,r,t);
        }
        else {
            cout<<query(l,r,t)<<endl;
        } 
    }
}
复制代码

 

posted @   liyishui  阅读(21)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)
点击右上角即可分享
微信分享提示