题意:
给一个数列,一些询问,问你区间$[l.r]$大于$K$的个数
题解:
又一个"人尽皆知傻逼题"?
我们用一个01序列表示当前询问时,该位置的数字是否对答案有贡献,
显然,对于询问$(l,r,k)$整个区间只有大于$k$的数字对答案有贡献,
那么离线思路就有了
按k排序询问,排序数字,遍历所有询问,对于每次询问$(l,r,k)$,把所有大于K的数字插进去...
复杂度O$(nlog(n)+klog(k))$
bit
#include <bits/stdc++.h> #define ll long long #define IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0) #define pp pair<int,int> #define rep(ii,a,b) for(int ii=a;ii<=b;ii++) #define per(ii,a,b) for(int ii=a;ii>=b;ii--) using namespace std; const int maxn=1e6+10; const int maxm=1e6*4+10; const int INF=0x3f3f3f3f; int casn,n,m,k; #define lb(x) x&-x ll bit[maxn],num[maxn]; void update(int pos,int x){while(pos<=n) bit[pos]+=x,pos+=lb(pos);} ll sum(int pos){ ll ans=0; while(pos)ans+=bit[pos],pos-=lb(pos); return ans; } ll query(int a,int b){return sum(b)-sum(a-1);} struct quest{int l,r,k,id;}ask[maxn]; int cmp1(quest a,quest b){ return a.k<b.k; } int cmp(int a,int b){ return num[a]<num[b]; } map<ll,int>pos; ll ans[maxn]; int rk[maxn]; int main(){ //#define test #ifdef test freopen("in.txt","r",stdin);freopen("out.txt","w",stdout); #endif scanf("%d",&n); rep(i,1,n) scanf("%d",num+i),rk[i]=i; sort(rk+1,rk+1+n,cmp); scanf("%d",&k); rep(i,1,k){ int a,b,c; scanf("%d%d%d",&a,&b,&c); ask[i]=(quest){a,b,c,i}; } sort(ask+1,ask+1+k,cmp1); int pos=1; rep(i,1,k){ while(pos<=n&&num[rk[pos]]<=ask[i].k){ update(rk[pos],1); pos++; } ans[ask[i].id]=ask[i].r-ask[i].l+1-query(ask[i].l,ask[i].r); } rep(i,1,k) printf("%d ",ans[i]); #ifdef test fclose(stdin);fclose(stdout);system("out.txt"); #endif return 0; }