Bzoj 3224.普通平衡樹 [ 權值線段樹 ]
阿新 • • 發佈:2018-11-09
Description
您需要寫一種資料結構(可參考題目標題),來維護一些數,其中需要提供以下操作:
1. 插入x數
2. 刪除x數(若有多個相同的數,因只刪除一個)
3. 查詢x數的排名(若有多個相同的數,因輸出最小的排名)
4. 查詢排名為x的數
5. 求x的前驅(前驅定義為小於x,且最大的數)
6. 求x的後繼(後繼定義為大於x,且最小的數)
Input
第一行為n,表示操作的個數,下面n行每行有兩個數opt和x,opt表示操作的序號(1<=opt<=6)
Output
對於操作3,4,5,6每行輸出一個數,表示對應答案
Sample Input
10
1 106465
4 1
1 317721
1 460929
1 644985
1 84185
1 89851
6 81968
1 492737
5 493598
Sample Output
106465
84185
492737
權值線段樹 ,平衡樹 ,Treap , AVL , 替罪羊樹 , 樹狀陣列 都可以寫 博主提供一種權值線段樹的
AC code:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long ll;
typedef pair<int,int>pii;
const int maxn = 1e5+50;
const int inf = 0x3f3f3f3f;
const int mod = 1e9+7;
struct segtree{
int l,r;
int sum;
}ss[maxn<<2];
struct Node{
int op;
ll w;
}node[maxn];
int cnt = 0;
ll vis[maxn];
void pushUp(int rt) {
ss[rt].sum = (ss[lson].sum + ss[rson].sum);
}
void build(int l,int r,int rt) {
ss[rt].l = l; ss[rt].r = r;
ss[rt].sum = 0;
if(l == r) return;
int mid = (l+r)>>1;
build(l,mid,lson); build(mid+1,r,rson);
}
void update(int pos,int val,int rt) {
if ( ss[rt].l == ss[rt].r ) {
ss[rt].sum += val; return;
}
int mid = (ss[rt].l + ss[rt].r) >> 1;
if ( mid >= pos ) update(pos,val,lson);
else update(pos,val,rson);
pushUp(rt);
}
/*********************************
re程式碼
re原因:當node[i].op 為 3 的時候tmp
有可能為1那麼tmp - 1 為零 l > r 條件永遠不滿足 因此re
在這個函式裡面加一句
if ( l > r ) return 0;也可以過
*********************************/
//int query(int l,int r,int rt) {
// if ( ss[rt].l == l && ss[rt].r == r ) {
// return ss[rt].sum;
// }
// int mid = (ss[rt].l + ss[rt].r) >> 1;
// if ( mid >= r ) return query(l,r,lson);
// else if ( l > mid ) return query(l,r,rson);
// else return query(l,mid,lson) + query(mid+1,r,rson);
//}
/********************************
ac程式碼
********************************/
int query(int l,int r,int rt) {
if ( ss[rt].l >= l && ss[rt].r <= r ) {
return ss[rt].sum;
}
int mid = (ss[rt].l + ss[rt].r) >> 1;
int ans = 0;
if ( mid >= l ) ans += query(l,r,lson);
if ( r > mid ) ans += query(l,r,rson);
return ans;
}
int Kth(int pos,int rt) {
if ( ss[rt].l == ss[rt].r ) return ss[rt].l;
int mid = (ss[rt].l + ss[rt].r ) >> 1;
if ( ss[lson].sum >= pos ) {
Kth(pos,lson);
} else {
Kth(pos-ss[lson].sum,rson);
}
}
void Print(int l,int r,int rt) {
if(l == r) {
printf("ss[%d].sum = %d\n",ss[rt].l,ss[rt].sum);
return;
}
int mid = (l+r)>>1;
Print(l,mid,lson); Print(mid+1,r,rson);
}
int main(){
int t; cin>>t;
for (int i = 1;i<=t;i++) {
scanf("%d %lld",&node[i].op, &node[i].w );
if ( node[i].op != 4 ) vis[++cnt] = node[i].w;
}
sort(vis+1,vis+cnt+1);
int len = unique(vis+1,vis+cnt+1) - vis; len--;
// printf("len = %d\n",len);
// for (int i = 1;i<=len;i++) printf("%lld ",vis[i]);
// printf("\n");
build(1,len,1);
for (int i = 1;i<=t;i++) {
int tmp;
if ( node[i].op != 4 )
tmp = lower_bound(vis+1,vis+len+1,node[i].w) - vis;
//printf("^ ^ %d %lld\n",tmp,vis[tmp]);
if(node[i].op == 1) {
update(tmp,1,1);
//Print(1,len,1);
} else if ( node[i].op == 2 ) {
update(tmp,-1,1);
} else if ( node[i].op == 3 ) {
printf("%d\n",query(1,tmp-1,1)+1);
} else if ( node[i].op == 4 ) {
//printf("node[i].w = %lld, Kth() = %d\n",node[i].w,Kth(node[i].w,1));
printf("%lld\n",vis[Kth(node[i].w,1)]);
} else if ( node[i].op == 5 ) {
//printf("node[i].w = %lld ,tmp = %d\n",node[i].w,tmp);
int ans = query(1,tmp-1,1);
int temp = Kth(ans,1);
//Print(1,len,1);
//printf("ans = %lld ,temp = %d\n",ans,temp);
printf("%lld\n",vis[temp]);
} else if ( node[i].op == 6 ) {
int ans = query(1,tmp,1);
int temp = Kth(ans+1,1);
printf("%lld\n",vis[temp]);
}
}
return 0;
}