2021CCPC河南省-小凯的书架(树状数组+二分)

原题链接:小凯的书架

题目大意:

给你一个数组,让你求出数组中的每一个数的左边第K个大于它的数,如果没有输出-1 .

解题思路:

其实这题暴力可以写。。。当然只会暴力是没有前途的。

主席树+二分也可以写,但主席树没学。。

太菜了wwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwwww

对于本题来说主席树和树状数组的作用都是一样的:设查询区间为 l-r,数为x  快速返回区间比 x

大的数的个数

为什么可以二分呢?

二分答案位置,位置越向左比 x 大的数的个数就越可能大,位置越向右反之

数状数组如何去查询呢?

树状数组可以维护一个动态的前缀和,从大到小排序,依次按原始编号加入树状数组,这样就可以查询啦

代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define guo312 std::ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define Inf LONG_LONG_MAX
#define inf INT_MAX
#define endl "\n"
using namespace std;
const int N=2e5+10;
int n,k,cnt[N],ans[N],s[N]; 
struct PW{int num,id;
}a[N]; 
bool cmp(PW s1,PW s2){if(s1.num==s2.num){return s1.id>s2.id;}else{return s1.num>s2.num;}
}
int lowbit(int x){return x&(-x);
}
void add(int x){for( ;x<=n;cnt[x]++,x+=lowbit(x));
}
int getnum(int x){int re=0;for( ;x>0;re+=cnt[x],x-=lowbit(x));return re;
}
bool check(int x,int id){return getnum(id-1)-getnum(x-1)>=k;
}
int main(){
guo312;int t; cin>>t;while(t--){cin>>n>>k;for(int i=1;i<=n;i++){cin>>a[i].num;a[i].id=i,s[i]=a[i].num;}sort(a+1,a+1+n,cmp);for(int i=1;i<=n;i++){add(a[i].id);if(getnum(a[i].id-1)>1;if(check(mid,a[i].id)) l=mid;else r=mid-1;}ans[a[i].id]=s[l];}}for(int i=1;i<=n;i++){cout<


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部