洛谷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; } } }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 【杭电多校比赛记录】2025“钉耙编程”中国大学生算法设计春季联赛(1)