Question
给定一个长为的数组,对其求
次询问,每次求
。
Solution
离线+树状数组
这里该如何用树状数组表示是个问题,
一开始我的想法是多开树状数组,显然必TLE,这里要结合离线。
我们把输入的数组,存为
形式,其中
放值,
放对应的位置。
我们将输入的询问放入中,按照询问的
从小到大排序。
这样排序的好处是,我们维护树状数组时,维护到则停下来,则当前答案就为所求答案,然后继续重复这种操作,答案的记录保存的位置和询问输入的顺序要一致。
Code
#include<bits/stdc++.h>
#define fi first
#define se second
using namespace std;
typedef long long ll;
typedef pair<int,int>P;
const double eps = 1e-8;
const int NINF = 0xc0c0c0c0;
const int INF = 0x3f3f3f3f;
const ll mod = 1e9 + 7;
const ll maxn = 1e6 + 5;
const int N = 1e5 + 5;
struct node{
int l,r,x,id;
bool operator < (const node & T) const{
return x<T.x;
}
}t[N];
int n,m;
pair<int,int>a[N];
int tree[N];
int ans[N];
inline int lowbit(int x){return x&-x;}
inline void add(int x){
while(x<=n){
tree[x]++;
x+=lowbit(x);
}
}
inline int ask(int x){
int ans=0;
for(;x;x-=lowbit(x)) ans+=tree[x];
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin>>n>>m;
for(int i=1;i<=n;i++) cin>>a[i].fi,a[i].se=i;
for(int i=1;i<=m;i++) cin>>t[i].l>>t[i].r>>t[i].x,t[i].id=i;
sort(a+1,a+1+n);
sort(t+1,t+1+m);
for(int i=1,k=1;i<=m;i++){
while(k<=n && a[k].fi<=t[i].x) add(a[k].se),++k;
ans[t[i].id]=ask(t[i].r)-ask(t[i].l-1);
}
for(int i=1;i<=m;i++) cout<<ans[i]<<'\n';
return 0;
}
京公网安备 11010502036488号