CF1354D - Multiset

CF1354D - Multiset

Question

给你一个数组长度为 n n n的数组 a   ( 1 ≤ a i ≤ n ) a\ (1\le a_i\le n) a (1ain),有 q q q次操作,每次操作输入 k k k
k > 0 k>0 k>0,数组中增加一个数 k k k
k < 0 k<0 k<0,数组中去掉第 − k -k k 小的数
若最后数组为空,则输出0,否则输出任意一个数组中存在的数。

Solution

1.二分答案
2.权值线段树
3.树状数组改改
这是一道模板题,写这篇博客主要是给自己开拓思维,解法比较多。

Code1 binary search

#include
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 = 1e6 + 5;

int n,T;
int a[N],q[N];

bool check(int x){
	int cnt=0;
	for(int i=1;i<=n;i++) if(a[i]<=x) cnt++;
	for(int i=1;i<=T;i++){
		if(q[i]<0){
			if(-q[i]<=cnt) cnt--;
		}
		else if(q[i]<=x) cnt++;
	}
	return cnt>0;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>T;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=T;i++) cin>>q[i];
	int L=1,R=n+1;
	while(L<R){
		int mid=(L+R)/2;
		if(check(mid)) R=mid;
		else L=mid+1;
	}
	cout<<(L<=n?L:0)<<'\n';
	return 0;
}

Code2 weight tree segement

#include
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 = 1e6 + 5;

int n,T;
int f[4*N];

void add(int l,int r,int v,int x,int t){
	if(l==r) f[v]+=t;
	else{
		int mid=(l+r)/2;
		if(x<=mid) add(l,mid,v*2,x,t);
		else add(mid+1,r,v*2+1,x,t);
		f[v]=f[v*2]+f[v*2+1];
	}
}

int kth(int l,int r,int v,int k){
	if(l==r) return l;
	else{
		int mid=(l+r)/2,s1=f[v*2],s2=f[v*2+1];
		if(k<=s1) return kth(l,mid,v*2,k);
		else return kth(mid+1,r,v*2+1,k-s1);
	}
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>T;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		add(1,n,1,x,1);
	}
	for(int i=1;i<=T;i++){
		int x;cin>>x;
		if(x>0) add(1,n,1,x,1);
		else add(1,n,1,kth(1,n,1,-x),-1);
	}
	if(!f[1]) cout<<0<<'\n';
	else cout<<kth(1,n,1,1)<<'\n';
	return 0;
}

Code3 BIT

#include
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 = 1048588;
const int lim = 1048576;

int n,T;
int bit[N];

void add(int pos,int val){
	for(int i=pos;i<=lim;i+=i&(-i)) bit[i]+=val;
}

int bsearch(int x){
	if(x==0) return 0;
	int pos=0;
	for(int i=lim/2;i>=1;i/=2){
		if(bit[pos+i]<x){
			x-=bit[pos+i];
			pos+=i;
		}
	}
	return pos+1;
}

int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>T;
	for(int i=1;i<=n;i++){
		int x;cin>>x;
		add(x,1);
	}
	int cnt=n;
	for(int i=1;i<=T;i++){
		int x;cin>>x;
		if(x>0) add(x,1),cnt++;
		else{
			x=bsearch(-x);
			add(x,-1),cnt--;
		}
	}
	cout<<(cnt==0?0:bsearch(1))<<'\n';
	return 0;
}

权值线段树kth

int find_kth(int k)
{
	int ans=0,sum=0,i;
	for(int i=20;i>=0;i--)
	{
		ans+=(1<<i);
		if(ans>=maxn||sum+bit[ans]>=k)
			ans-=(1<<i);
		else
			sum+=bit[ans];
	}
	return ans+1;
}

你可能感兴趣的:(二分,权值线段树,树状数组)