思路:做法比較多,我寫的是權值線段樹套平衡樹,平衡樹內維護該權值區間內各元素位置,每次查詢從線段樹根結點開始左右走就可以了。現在問題是如何解決帶插入的情況下快速比較兩個位置標號的前後關係,我們可以用替罪羊樹維護,我們給每個位置標號定個rank區間,例如根定為[0,1e18],定其rank值為中點5*1e17,那麼他左兒子的rank區間為[0,5*1e17],右兒子為[5*1e17,1e18],這樣我們每次只要o(1)就可以比較兩個位置標號的前後關係,我們用double存這個rank,如果樹深度太高,rank精度可能不夠,我們重構替罪羊樹時一併重構rank即可解決。總複雜o((n+q)*log^2),這個**跑了28s左右。
#includeinlineintread()
#define mn 70000
#define n 131072
#define lg 17
#define nd lg*mn
struct
sgt
void ins(int*x,int z,int k,double lx,double
rx)
++s[*x];
if(k2)ins(lc+*x,z,k,lx,rk[*x]);
else ins(rc+*x,z,k-s[lc[*x]]-1,rk[*x],rx);
if(s[lc[*x]]>s[*x]*alpha||s[rc[*x]]>s[*x]*alpha)rb=x;
}void dfs(int x)
void insert(int x,int
k)
int find(int
k)
}sgt;
int a[mn+5],rt[n*2+5],d[nd+5
];namespace
treap
inline
intran()
inline
void up(int x)
void rotate(int
x)
void ins(int&x,int f,int
z)
++s[x];ins(c[x][cmp(x,z)],x,z);
}void del(int
x)
c[fa[x]][c[fa[x]][
1]==x]=0
;
for(int i=x;(i=fa[i])>0
;)up(i);
}int sum(int x,int z,int
f)
};void ins(int k,int
x)void del(int k,int
x)int query(int k,int l,int r,int
x)int
main()
}
bzoj3065帶插入區間K小值
這題其實好像很難,但是聽werkeytom ftd說可以用塊鏈水,於是就很開心地去打了個塊狀鍊錶套主席樹,插入操作就直接插到乙個塊中,注意如果塊的大小2 block就將塊分開,注意每乙個修改或插入都要修改後繼的狀態,貼 include include include include include ...
BZOJ3065 帶插入區間K小值
因為需要支援插入,所以外層需要乙個平衡樹,替罪羊樹比較好寫 內層需要帶修改,求k小值,可以使用權值線段樹維護平衡樹每個節點子樹內的所有權值,求k小值時二分查詢 所以是平衡樹套權值線段樹 include include include include include using namespace s...
BZOJ3065 替罪羊樹套線段樹
以前看到這題都瑟瑟發抖,終於過了心情舒暢。按下標為關鍵字建替罪羊樹,每個結點開乙個權值線段樹,維護的這個結點代表的子樹的資訊。這題還得垃圾 自己yy的,不知對不對.include include using namespace std define m l r 1 define l x t x s ...