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; }