题解 数数
可持久化平衡树看上去很行的样子,但是我不会啊。。。
先来考虑一个简化版的问题:求区间 中 的元素个数。
这显然是好做的,用权值树状数组就行。
回到本题,显然:询问区间 中 的个数,等价与区间 的答案减去区间 的答案。所以,我们将一个询问拆成上述形式的两个询问,并且附上一个 ,表示这个询问对答案是加还是减,如果是加,就赋值位 ,减则赋值为 。即:
struct node { int r,id,k,h; //分别表示,右边界,第几个问题,加还是减,h的值 };
然后按照右边界排序,依次做权值树状数组即可。
由于 的范围很大,所以先要离散化。
完整代码:
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int T,n,q,m; int a[N],b[N]; int ans[N]; int tr[N]; struct node { int k,r,h,id; }; vector<node> que; int cmp(node x,node y) { return x.r<y.r; } int find(int x) { return lower_bound(b+1,b+1+m,x)-b; } int lowbit(int x) { return x&(-x); } void modify(int nd,int x) { for(int i=nd;i<=m;i+=lowbit(i)) tr[i]+=x; } int query(int nd) { int ans=0; for(int i=nd;i;i-=lowbit(i)) ans+=tr[i]; return ans; } void Solve() { cin>>n>>q; for(int i=1;i<=n;i++) { cin>>a[i]; b[++m]=a[i]; } for(int i=1;i<=q;i++) { int l,r,h; cin>>l>>r>>h; b[++m]=h; que.push_back({1,r,h,i}); que.push_back({-1,l-1,h,i}); } sort(b+1,b+1+m); m=unique(b+1,b+1+m)-b-1; sort(que.begin(),que.end(),cmp); int nd=0; for(auto t:que) { while(nd+1<=t.r) {modify(find(a[nd+1]),1); nd++;} ans[t.id]+=t.k*query(find(t.h)); } for(int i=1;i<=q;i++) cout<<ans[i]<<' '; cout<<endl; } void Clear() { for(int i=1;i<=m;i++) b[i]=0; for(int i=1;i<=n;i++) a[i]=0; for(int i=1;i<=m;i++) tr[i]=0; for(int i=1;i<=q;i++) ans[i]=0; n=m=q=0; que.clear(); } int main() { cin>>T; while(T--) { Solve(); Clear(); } return 0; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效