ZOJ 2112 块状链表


犯了很多SB的错误。。


数据规模是 50000, 那么一个块大概230。  

做法是块状思想,  二分答案计算它的 rank是否满足,满足则输出这个答案

时间复杂度 n*sqrt(n)*logn        十秒的时限妥妥的AC。。


//tpl
//ipqhjjybj_tpl.h
//header.h
#include <cstdio>
#include <cstdlib>
#include <map>
#include <set>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <vector>
#include <string>
#include <queue>
#include <sstream>
#include <math.h>

#define mp(x,y) make_pair(x,y)
#define pii pair<int,int>
#define pLL pair<long long ,long long>
#define pb(x) push_back(x)
#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 = 55555;
const int Sqrt = 240;
int n,m;
int a[N];
char s[10];
vector<int> vec[444];
vector<int> h[444];
vector<int> fh;
int maxK;
void modify(int l,int val){
	int k1 = l/Sqrt ,l1 = l%Sqrt;
	int tmp = vec[k1][l1];
	if(tmp == val) return;
	vec[k1][l1] = val;
	int pos = lower_bound(h[k1].begin(),h[k1].end(),tmp) - h[k1].begin();
	int sz = h[k1].size();
	l1 = pos;
	h[k1][pos] = val;
	if(val > tmp){	
		while( l1 + 1 < sz && h[k1][l1] > h[k1][l1+1])
			swap(h[k1][l1], h[k1][l1+1]) , l1++;
	}else{
		while( l1 > 0 && h[k1][l1] < h[k1][l1-1]){
			swap(h[k1][l1], h[k1][l1-1]),l1--;
		}
	}
}
// 返回 [l,r] 区间内小于 val 的数的数目
// 并且 统计 = val 的数目 存于 exis
int query(int l,int r,int val,int &exis){ 
	int k1 = l/Sqrt , l1 = l % Sqrt , k2 = r/Sqrt , l2 = r%Sqrt;
	int ret = 0; exis = 0;
	l2++;
	if(k1 == k2){	
		rep(i,l1,l2) 
			if(vec[k1][i] < val){
				ret++;
			}
			else if(vec[k1][i] == val)
				exis++;
	}else{
		rep(i,k1+1,k2){
			int pos = lower_bound(h[i].begin(),h[i].end(),val) - h[i].begin();
			int kk = upper_bound(h[i].begin(),h[i].end(), val) - h[i].begin();

			pos = min(pos,(int)h[i].size());
			kk = min(kk,(int)h[i].size());

			if(pos!=h[i].size() && h[i][pos] == val) 
				exis += kk - pos;
			ret += pos ;
		}
		int sz = vec[k1].size();
		rep(i,l1,sz)
			if(vec[k1][i] < val){
				ret++;
			}
			else if(vec[k1][i] == val)
				exis++;
		rep(i,0,l2)
			if(vec[k2][i] < val){	
				ret++;
			}
			else if(vec[k2][i] == val)
				exis++;
	}
	return ret;
}
int solve(int ql,int qr,int k){
	int l = 0,r = fh.size()-1 , ans=-1;
	int exis;
	while(l <= r){
		int m = (l+r)>>1;
		int mid_val = fh[m];
		int ret = query(ql,qr,mid_val,exis);

		if( ret < k && ret+exis >= k){
			ans = mid_val; break; 
		}else if(ret < k){
			l = m + 1;
		}else{
			r = m - 1;
		}
	}
	return ans;
}
struct ed{
	int l,r,k;
	char c;
	void input(){
		scanf("%s %d %d",s,&l,&r);
		l--;
		if((c = s[0]) == 'Q'){
			r--;
			scanf("%d",&k);
		}
	}
}E[N<<1];
int main(){
	int tt;
	scanf("%d",&tt);
	while(tt--){

		scanf("%d %d",&n,&m);
		maxK = n/Sqrt+4;
		rep(i,0,maxK)
			vec[i].clear(),h[i].clear();
		rep(i,0,n) scanf("%d",a+i);
		rep(i,0,n){
			vec[i/Sqrt].pb(a[i]),h[i/Sqrt].pb(a[i]);
		}
		
		rep(i,0,maxK) sort(h[i].begin(),h[i].end());
		rep(i,0,m) E[i].input();
		
		fh.clear();
		rep(i,0,m) if(E[i].c=='C') fh.pb(E[i].r);
		rep(i,0,n) fh.pb(a[i]);
		sort(fh.begin(),fh.end());
		fh.erase(unique(fh.begin(),fh.end()),fh.end());
		
		rep(i,0,m){
			int l = E[i].l,r = E[i].r;
			char c = E[i].c ;
			if(c == 'Q'){
				int k = E[i].k;
				printf("%d\n",solve(l,r,k));
			}else{
				modify(l,r);
			}
		}
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值