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 64 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
9 hint
1.n和m的資料範圍:n,m<=50000
2.序列中每個數的資料範圍:[0,1e8]
3.雖然原題沒有,但事實上5操作的k可能為負數
由於這題既要維護區間的資訊,又要搞排名,前驅,後繼等平衡樹的操作。所以這題的思路就是線段樹套平衡樹(樹套樹)
我們對於線段樹的每乙個區間都建立乙個平衡樹,那麼我們就可以進行操作了。我們乙個乙個來看:
操作1:我們查詢線段樹的區間,將每一小塊區間裡小於x的數累加,再加1(x自己)即可。
現在我們來講操作2:直接二分答案,二分乙個權值,然後查詢區間裡有的排名,如果剛好等於k,那麼就讓r=mid
,這樣可以保證最終的點取到所求的x的權值vx(因為vx-1的排名肯定是x的排名-1)
code:int getpl(int l,int r,int k)
return cl-1;
}
#include
#define maxn 3000005
#define inf 2147483647
using namespace std;
intread()
int n,m,mx,dist,tot,a[maxn],rt[maxn];
int son[maxn][2],fa[maxn],val[maxn],siz[maxn],ct[maxn];
void clear(int k)
void pushup(int k)
void rotate(int k)
void splay(int i,int k,int top)
if(!top) rt[i]=k;
}void splayinsert(int p,int
x) int
last=0;
while(1)
last=wh;wh=son[wh][x>val[wh]];
if(!wh)
}splay(p,wh,0);
}int splayrank(int p,int k)
else
if(val[wh]==k) return ret+(son[wh][0]?siz[son[wh][0]]:0);}}
return ret;
}int access(int p,int
x) wh=son[wh][x>val[wh]];
}}int pre(int p)
void splaydelete(int p,int elemental)
if(!son[x][0]&&!son[x][1])
if(!son[x][0])
if(!son[x][1])
int wh=pre(p),oldrt=rt[p];
splay(p,wh,0);
son[rt[p]][1]=son[oldrt][1];fa[son[oldrt][1]]=rt[p];
clear(oldrt);pushup(rt[p]);
}int getpre(int p,int
x) else wh=son[wh][0];
}return dist;
}int getsuff(int p,int
x) else wh=son[wh][1];
}return dist;
}void seginsert(int k,int l,int r,int p,int
x)void segrank(int k,int l,int r,int l,int r,int
x) int mid=(l+r)>>1;
if(l<=mid) segrank(k<<1,l,mid,l,r,x);
if(r>mid) segrank(k<<1|1,mid+1,r,l,r,x);
}void segtransform(int k,int l,int r,int p,int
x) int mid=(l+r)>>1;
if(p<=mid) segtransform(k<<1,l,mid,p,x);
else segtransform(k<<1|1,mid+1,r,p,x);
}void segpre(int k,int l,int r,int l,int r,int
x) int mid=(l+r)>>1;
if(l<=mid) segpre(k<<1,l,mid,l,r,x);
if(r>mid) segpre(k<<1|1,mid+1,r,l,r,x);
}void segsuff(int k,int l,int r,int l,int r,int
x) int mid=(l+r)>>1;
if(l<=mid) segsuff(k<<1,l,mid,l,r,x);
if(r>mid) segsuff(k<<1|1,mid+1,r,l,r,x);
}int getpl(int l,int r,int k)
return cl-1;
}int main()
for(int i=1;i<=m;i++)
if(type==2)
if(type==3)
if(type==4)
if(type==5)
}return
0;}
BZOJ 3196 二逼平衡樹 樹套樹
description 您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 in...
樹套樹 BZOJ3196 二逼平衡樹
您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢 x在區間內的排名 2.查詢區間內排名為 k 的值 3.修改某一位置上的數值 4.查詢 x 在區間內的前趨 前趨定義為小於 x,且最大的數 5.查詢 x 在區間內的後繼 後繼定義為大於 x,且最小的數 第一行兩個...
Bzoj3196 二逼平衡樹
您需要寫一種資料結構 可參考題目標題 來維護乙個有序數列,其中需要提供以下操作 1.查詢k在區間內的排名 2.查詢區間內排名為k的值 3.修改某一位值上的數值 4.查詢k在區間內的前驅 前驅定義為小於x,且最大的數 5.查詢k在區間內的後繼 後繼定義為大於x,且最小的數 額,這個題,看了一眼就知道是...