D. Multiset(權值線段樹 or 樹狀數組+二分)Educational Codeforces Round 87 (Rated for Div. 2)

在這裏插入圖片描述
在這裏插入圖片描述
題目大意:
給你一個長度爲nn的序列,以及qq次詢問qiqi,如果qi>0qi>0,在序列中插入qiqi,如果qi<0qi<0,在序列中刪除第qi|qi|大的數,問你qq詢問後,如果序列中爲空,輸出00即可,否則輸出序列中任意一個數即可。
思路:
所有操作無非就是刪除第kk大數,增加第kk大數,我們可以用桶排序的思路建立線段樹我們稱爲它爲權值線段樹,這個題n=1e6n=1e6用權值線段樹時間複雜度O(nlogn)O(nlogn)是可以過的,但是結構體開不了會超空間這裏要換一種存儲方式,然後就是線段樹的單點更新,單點詢問操作(都很簡單),還有權值線段樹的第kk大操作(相當於前綴和也很簡單)。
代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
int tree[maxn << 2];
void update(int rt,int x,int l,int r){
	if(l == r && l == x){
		tree[rt]++;
		return ;
	}
	int mid = l + r >> 1;
	if(x <= mid)update(rt << 1,x,l,mid);
	else update(rt << 1 | 1,x,mid + 1,r);
	tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
bool check(int rt,int id,int l,int r){
	if(l == r && l == id){
		if(tree[rt] > 0)return true;
		else return false;
	}
	int mid = l + r >> 1;
	if(id <= mid)return check(rt << 1,id,l,mid);
	else return check(rt << 1 | 1,id,mid + 1,r);
}
void kth(int rt,int k,int l,int r){
	if(l == r){
		tree[rt]--;return;
	}
	int mid = l + r >> 1;
	if(tree[rt << 1] >= k)kth(rt << 1,k,l,mid);
	else kth(rt << 1 | 1,k - tree[rt << 1],mid + 1,r);
	tree[rt] = tree[rt << 1] + tree[rt << 1 | 1];
}
void solved(){
	int n,q;scanf("%d%d",&n,&q);
	for(int i = 1; i <= n; i++){
		int x;scanf("%d",&x); 
		update(1,x,1,n);
	}
	for(int i = 1; i <= q; i++){
		int x;scanf("%d",&x);
		if(x > 0)update(1,x,1,n);
		else {
			x *= -1;kth(1,x,1,n);
		}
	}
	if(tree[1] <= 0){
		printf("0\n");
	}else{
		for(int i = 1; i <= n; i++){
			if(check(1,i,1,n)){
				cout<<i<<endl;break;
			}
		}
	}
}
int main(){
	solved();
	return 0;
}

數組數組做法,其實和桶排序類似。
代碼:

#include<bits/stdc++.h>
using namespace std;

const int maxn = 1e6 + 10;
struct bit{
	int c[maxn];
	int lowbit(int x){
		return x & -x;
	}
	void update(int x,int v = 1){
		for(; x <= maxn; x += lowbit(x)){
			c[x] += v;
		}
	} 
	int query(int x){
		int s = 0;
		for(; x ; x -= lowbit(x)){
			s += c[x];
		}
		return s;
	}
}BIT;
void solved(){
	int n,q;scanf("%d%d",&n,&q);
	for(int i = 1; i <= n; i++){
		int x;scanf("%d",&x);BIT.update(x);
	}
	for(int i = 1; i <= q; i++){
		int x;scanf("%d",&x);
		if(x > 0)BIT.update(x);
		else{
			x *= -1;
			int l = 1,r = n;
			while(l < r){
				int mid = l + r >> 1;
				if(BIT.query(mid) >= x)r = mid;
				else l = mid + 1;
			}
			BIT.update(r,-1);
		}
	}
	int ans = BIT.query(n);
	if(ans <= 0){
		cout<<"0"<<endl;
	}else{
		for(int i = 1; i <= n ; i++){
			if(BIT.query(i) - BIT.query(i - 1) > 0){
				cout<<i<<endl;break;
			}
		}
	}
}
int main(){
	solved();
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章