树状数组写区间最大值

15 篇文章 0 订阅
5 篇文章 0 订阅


莫队算法。。不过 TLE了。。 ++


#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <cmath>

#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define rep(i,j,k) for(int i = j; i < k;i++)

#define MAX(x,a)  x=((x)<(a))?(a):(x); 
#define MIN(x,a)  x=((x)>(a))?(a):(x); 

using namespace std;

const int N = 1e5+10;
int SQRT = 333;
int n,m;

template <class T>  
inline void scan_d(T &ret) {  
    char c; ret=0;  
    while((c=getchar())<'0'||c>'9');  
    while(c>='0'&&c<='9') ret=ret*10+(c-'0'),c=getchar();  
}  
//适用于正负整数  
template <class T>  
inline bool fuckD(T &ret) {  
   char c; int sgn;  
   if(c=getchar(),c==EOF) return 0; //EOF  
   while(c!='-'&&(c<'0'||c>'9')) c=getchar();  
   sgn=(c=='-')?-1:1;  
   ret=(c=='-')?0:(c-'0');  
   while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');  
   ret*=sgn;  
   return 1;  
}  
 
struct ed{
	int l,r,k,ind;
	void input(){
		scan_d(l),scan_d(r),scan_d(k);
		l--,r--;
	}
}E[N>>3];
bool cmp(int i,int j){
	if(E[i].l/ SQRT == E[j].l / SQRT)
		return E[i].r < E[j].r;
	return E[i].l < E[j].r;
}
int idx[N];
int a[N],b[N];
int ans[N];

#define lowbit(t) (t&(-t))
int cntt;
int sum[N];
void update(int pos,int val){
	for( ; pos <= cntt;pos+=lowbit(pos))
		sum[pos]+=val;
}
int query(int pos){
	int ret = 0;
	for( ; pos ;pos-=lowbit(pos))
		ret += sum[pos];
	return ret;
}
int solve(int kth){
	int l = 1, r = cntt;
	int ret = 0 , ss,mid;
	while(l<=r){
		mid = (l+r)>>1;
		ss = query(mid);
		if(ss < kth){
			l = mid+1;
		}else if(ss > kth){
			r = mid-1;
		}else{
			ret = mid ;
			r=mid-1;
		}
	}
	return ret;
}
int main(){
	while(scanf("%d %d",&n,&m)!=EOF){
		rep(i,0,n) fuckD(a[i]);
		SQRT = (int)sqrt(1.0*n);
		memcpy(b,a,sizeof(a));
		sort(b,b+n);
		cntt = unique(b,b+n)-b;
		rep(i,0,n)a[i] = lower_bound(b,b+cntt,a[i])-b;
		rep(i,0,m)E[i].input(),E[i].ind=i;
		rep(i,0,m)idx[i]=i;
		
		sort(idx,idx+m,cmp);
		memset(sum,0,sizeof(sum));
		int pl = 0,pr = -1;
		
		rep(i,0,m){
			int l = E[idx[i]].l,r = E[idx[i]].r,k = E[idx[i]].k, ind = E[idx[i]].ind;
			while(pr < r) update(a[++pr]+1,1);
			while(pr > r) update(a[pr--]+1,-1);
			while(pl > l) update(a[--pl]+1,1);
			while(pl < l) update(a[pl++]+1,-1);
			ans[ind] = solve(k)-1;
		}
		rep(i,0,m)
			printf("%d\n",b[ans[i]]);
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值