1. 程式人生 > >bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡樹 (線段樹套Treap)

bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡樹 (線段樹套Treap)

put clas 結構 online input 維護 amp bbs 查詢

鏈接:https://www.lydsy.com/JudgeOnline/problem.php?id=3196

題面;

3196: Tyvj 1730 二逼平衡樹

Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 6372 Solved: 2406
[Submit][Status][Discuss]

Description

您需要寫一種數據結構(可參考題目標題),來維護一個有序數列,其中需要提供以下操作:
1.查詢k在區間內的排名
2.查詢區間內排名為k的值
3.修改某一位值上的數值
4.查詢k在區間內的前驅(前驅定義為小於x,且最大的數)
5.查詢k在區間內的後繼(後繼定義為大於x,且最小的數)

Input

第一行兩個數 n,m 表示長度為n的有序序列和m個操作
第二行有n個數,表示有序序列
下面有m行,opt表示操作標號
若opt=1 則為操作1,之後有三個數l,r,k 表示查詢k在區間[l,r]的排名
若opt=2 則為操作2,之後有三個數l,r,k 表示查詢區間[l,r]內排名為k的數
若opt=3 則為操作3,之後有兩個數pos,k 表示將pos位置的數修改為k
若opt=4 則為操作4,之後有三個數l,r,k 表示查詢區間[l,r]內k的前驅
若opt=5 則為操作5,之後有三個數l,r,k 表示查詢區間[l,r]內k的後繼

Output

對於操作1,2,4,5各輸出一行,表示查詢結果

Sample Input

9 6
4 2 2 1 9 4 0 1 1
2 1 4 3
3 4 10
2 1 4 3
1 2 5 9
4 3 9 5
5 2 8 5

Sample Output

2
4
3
4
9

HINT

1.n和m的數據範圍:n,m<=50000


2.序列中每個數的數據範圍:[0,1e8]


3.雖然原題沒有,但事實上5操作的k可能為負數 思路; 線段樹套個Treap就完事了,ls寫成了rs,找了一晚上的錯,真實自閉 實現代碼:
#include<bits/stdc++.h>
using
namespace std; #define ls t[x].ch[0] #define rs t[x].ch[1] #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 1e5+10; const int inf = 2147483647; int idx,n; struct node{ int ch[2],cnt,siz,val,rd; }t[M*50]; int root[M<<2],a[M]; void up(int x){ t[x].siz = t[ls].siz + t[rs].siz+t[x].cnt; } void rotate(int &x,int d){ int son = t[x].ch[d]; t[x].ch[d] = t[son].ch[d^1]; t[son].ch[d^1] = x; up(x); up(x=son); } void ins(int &x,int val){ if(!x){ x = ++idx; t[x].cnt = t[x].siz = 1; t[x].val = val,t[x].rd = rand(); return ; } t[x].siz ++; if(t[x].val == val){ t[x].cnt++; return ; } int d = t[x].val < val; ins(t[x].ch[d],val); if(t[x].rd > t[t[x].ch[d]].rd) rotate(x,d); } void del(int &x,int val){ if(!x) return ; if(t[x].val == val){ if(t[x].cnt > 1){ t[x].cnt--,t[x].siz--;return ; } bool d = t[ls].rd > t[rs].rd; if(ls == 0||rs == 0) x = ls+rs; else rotate(x,d),del(x,val); } else t[x].siz--,del(t[x].ch[t[x].val<val],val); up(x); } int rk(int x,int val){ if(!x) return 0; if(t[x].val == val) return t[ls].siz; if(t[x].val > val) return rk(ls,val); return rk(rs,val)+t[ls].siz + t[x].cnt; } int pre(int x,int val){ if(!x) return -inf; if(t[x].val >= val) return pre(ls,val); return max(pre(rs,val),t[x].val); } int nex(int x,int val){ if(!x) return inf; if(t[x].val <= val) return nex(rs,val); return min(nex(ls,val),t[x].val); } void print(int x){ if(!x) return ; print(ls); printf("%d ",t[x].val); print(rs); } void update(int p,int l,int r,int rt){ ins(root[rt],a[p]); if(l == r) return ; mid; if(p <= m) update(p,lson); else update(p,rson); } int get_rank(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ return rk(root[rt],c); } int ret = 0; mid; if(L <= m) ret += get_rank(L,R,c,lson); if(R > m) ret += get_rank(L,R,c,rson); return ret; } int get_val(int x,int y,int k){ int l = 0,r = inf,ret ; while(l < r){ mid; int ans = get_rank(x,y,m,1,n,1)+1; if(ans <= k) { ret = m;l = m+1; } else r = m; } return ret; } void change(int p,int c,int l,int r,int rt){ del(root[rt],a[p]); ins(root[rt],c); if(l == r) return ; mid; if(p <= m) change(p,c,lson); else change(p,c,rson); } int get_pre(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ return pre(root[rt],c); } mid; int ret = -inf; if(L <= m) ret = max(ret,get_pre(L,R,c,lson)); if(R > m) ret = max(ret,get_pre(L,R,c,rson)); return ret; } int get_nex(int L,int R,int c,int l,int r,int rt){ if(L <= l&&R >= r){ return nex(root[rt],c); } mid; int ret = inf; if(L <= m) ret = min(ret,get_nex(L,R,c,lson)); if(R > m) ret = min(ret,get_nex(L,R,c,rson)); return ret; } void ct(int l,int r,int rt){ cout<<"L R: "<<l<<" "<<r<<endl; print(root[rt]); cout<<endl; if( l == r) return ; mid; ct(lson); ct(rson); } int main() { // freopen("D:\\1.txt","r",stdin); //freopen("D:\\2.txt","w",stdout); int m,op,x,y,z; scanf("%d%d",&n,&m); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); update(i,1,n,1); } //ct(1,n,1); while(m--){ scanf("%d",&op); scanf("%d%d",&x,&y); if(op!=3) scanf("%d",&z); if(op == 1) printf("%d\n",get_rank(x,y,z,1,n,1)+1); else if(op == 2) printf("%d\n",get_val(x,y,z)); else if(op == 3) change(x,y,1,n,1),a[x]=y; else if(op == 4) printf("%d\n",get_pre(x,y,z,1,n,1)); else if(op==5) printf("%d\n",get_nex(x,y,z,1,n,1)); } return 0; }

bzoj 3196 && luogu 3380 JoyOI 1730 二逼平衡樹 (線段樹套Treap)