您的位置:首页 > 理论基础 > 数据结构算法

acm数据结构整理

2015-03-12 14:32 183 查看
一、区间划分
//区间划分+持久化并查集:区间连通情况统计。
inline bool comp(Ask x, Ask y){return x.km == y.km ? x.l > y.l : x.km > y.km ; }
inline void init()//把编号相同的放一起,l从大到小;{
int i ;
ms = sqrt(1.0*n) ; //大小
mg = n/ms ; //块数
mg = mg*ms == n ? mg : mg + 1 ;
for(i = 1 ; i <= n ; i ++) e[i].clear() ;
}
/*********************持久化并查集**********************************/
void solve()//区间划分{
int i = 1, j, k, l, r ;
sort(ask+1, ask+1+q, comp) ;
while(i <= q) //询问
{
k = ask[i].km ;
for(; i <= q && ask[i].km == k && ask[i].l > (k-1)*ms ; i ++) //处理区间小于ms的询问
ans[ask[i].no] = bfAnswer(i) ;
if(i > q || ask[i].km != k ) //全部为小区间
continue ;
r = (k-1)*ms ; //最右端
initSet(lp, 1, r) ; //初始化并查集 ;
for(j = 1 ; j <= r ; j ++) vis[j] = 0 ;
while(i <= q && ask[i].km == k ) //求解第k块的所有大询问;
{
l = ask[i].l ;
for(j = r ; j >= l ; j -- ) //加入顶点j
addVex(lp, j, (k-1)*ms) ;
r = j ;
for(; i <= q && ask[i].km == k && ask[i].l == l ; i ++)
//计算所有左端等于l的区间;
{
ans[ask[i].no] = unionRSet(ask[i].no, l, (k-1)*ms+1, ask[i].r ) ; //右端暴力合并 ;
}
}
}
}
二、2B树:动态区间比x小的数的个数。
void DT_insert(int rt, int x, int s ){
int i = DN, j, p ;
getBinary(x) ;
j = dig[i--] ;
if(root[rt].next[j] == -1)
{
root[rt].next[j] = ++ tot ;
pool[tot].set() ;
}
if(!j) root[rt].sum += s ;
p = root[rt].next[j] ;
while(i)
{
j = dig[i--] ;
if(pool[p].next[j] == -1)
{
pool[p].next[j] = ++ tot ;
pool[tot].set() ;
}
if(!j)pool[p].sum += s ;
p = pool[p].next[j] ;
}
}
int DT_count(int rt, int x){
int i = DN, j, p, ans = 0 ;
getBinary(x) ;
j = dig[i--] ;
if(j) ans += root[rt].sum ;
if(root[rt].next[j] == -1) return ans ;
p = root[rt].next[j] ;
while(i)
{
j = dig[i--] ;
if(j) ans += pool[p].sum ;
if(pool[p].next[j] == -1) return ans ;
p = pool[p].next[j] ;
}
return ans ;
}
void DT_build(){
int i, k ;
size = sqrt(double(n)) ;
mg = n/size ;
mg = mg*size == n ? mg : mg+1 ;
for(i = 1 ; i <= mg ; i ++) root[i].set() ;
for(i = 1 ; i <= n ; i ++)
{
k = (i-1)/size + 1 ;
DT_insert(k, ar[i], 1) ;
}
bs = 10*size ;
bmg = n/bs ;
bmg = bmg*bs == n ? bmg : bmg + 1 ;
for(i = 1 ; i <= bmg+1 ; i ++) root[MAXS+i].set() ;
for(i = 1 ; i <= n ; i ++)
{
k = (i-1)/bs + 1 ;
DT_insert(MAXS+k, ar[i], 1) ;
}
}
int DT_query(int l, int r, int x){
int i, k, ans = 0, bk ;
k = (l-1)/size + 1 ;
k = size*(k-1)+1 == l ? k : k + 1 ;  //前
for(i = l ; i <= r && i < (k-1)*size+1 ; i ++) ans = ar[i] < x ? ans+1 : ans ;
for(; i <= r && r-i+1 >= size && (k%10 != 1) ; i += size, k ++) //小块
ans += DT_count(k, x) ;
for(bk = (k-1)/10+1 ; i <= r && r-i+1 >= bs ; i += bs, bk ++, k += 10)
ans += DT_count(MAXS+bk, x) ;//大块
for(; i <= r && r-i+1 >= size ; i += size, k ++) //小块
ans += DT_count(k, x) ;
for(; i <= r ; i ++) ans = ar[i] < x ? ans+1 : ans ;
return ans ;
}
三、树链剖分
1. 树上区间[u, v] 异或 x 的最大值
// 持久化2B树 + 树链剖分(区间可直接合并)
inline void insert(int rt, int x) ; //建一颗空树
inline void addNumber(int pre, int &rt, int id, int x){//持久化
int i = SD, p ;
bool j ;
rt = ++dcnt ; p = rt ;
while(i >= 0 )
{
pool[p] = pool[pre] ;
j = x&(1<<i) ;
pool[p].mx[j] = id ;
pool[p].next[j] = ++dcnt ;
p = dcnt ;
pre = pool[pre].next[j] ;
i -- ;
}
pool[p].x = x ;
}
inline int DTcount(int rt,int l,int x)//计算前缀树[1,r]中下标>=l的与x的最大异或值
/*******c******************树链剖分*************************/
void DFS(int u){
int i, to ;
siz[u] = 1 ; son[u] = 0 ;
for(i = head[u] ; i != -1 ; i = e[i].next )
{
to = e[i].to ;
if(to != fa[u])
{
fa[to] = u ;
dep[to] = dep[u] + 1 ;
DFS(to) ;
if(siz[son[u]] < siz[to]) son[u] = to ;
siz[u] += siz[to] ;
}
}
}
void cutLink(int u, int tp){
w[u] = ++cnt ;
top[u] = tp ;
if(son[u]) cutLink(son[u], tp) ;
for(int i = head[u] ; i != -1 ; i = e[i].next)
{
int to = e[i].to ;
if(to != fa[u] && to != son[u]) cutLink(to, to) ;
}
}
void buildTree(){
dep[1] = 1 ;
cnt = fa[1] = siz[0] = 0 ;
DFS(1) ;
cutLink(1, 1) ;
int i ;
for(i = 1 ; i <= n ; i ++) val[w[i]] = ar[i] ;
pool[0].set() ;
dcnt = T[0] = 0 ;
for(i = 1 ; i <= cnt ; i ++) insert(T[0], val[i]) ;
for(i = 1 ; i <= cnt ; i ++) addNumber(T[i-1], T[i], i, val[i]) ;//持久化思
}
int getAns(int u, int v, int x){
int ans = 0, tu = top[u], tv = top[v], tmp ;
if(u == v) return DTcount(T[w[u]], w[v], x) ; ;
while(tu != tv) //如果不在同一条链上
{
if(dep[tu] < dep[tv]) {swap(tu, tv) ; swap(u, v) ; }
tmp = DTcount(T[w[u]], w[tu], x ) ; //查询从u到tu的父亲的最大值
ans = max(ans, tmp) ;
u = fa[tu] ;
tu = top[u] ;
}
if(dep[u] < dep[v]) swap(u, v) ;
tmp = DTcount(T[w[u]], w[v], x) ;
return max(ans, tmp) ;
}
2. BFS实现建树
int leaf[MAXN], ns[MAXN], ct[MAXN];
void BFS(int rt){
int i, h = 0, t = 0, l = 0, r = 0 ;
int u, to ;
que[t++] = rt ;
for(i = 1 ; i <= n ; i ++)
{
siz[i] = 1 ;
ct[i] = ns[i] = son[i] = 0 ;
}
while (h < t) // calculate the dep.
{
u = que[h++] ;
for(i = head[u] ; i != -1 ; i = e[i].next)
{
to = e[i].to ;
if(to != fa[u])
{
ns[u] ++ ;
fa[to] = u ;
dep[to] = dep[u] + 1 ;
que[t++] = to ;
}
}
}
for(i = 1 ; i <= n ; i ++) if(ns[i] == 0) leaf[r++] = i ;
while(l < r)
{
to = leaf[l++] ;
u = fa[to] ;
siz[u] += siz[to] ; ct[u] ++ ;
if(ct[u] == ns[u] && u ) leaf[r++] = u ;
}
h = t = 0 ;
que[t++] = rt ;
siz[0] = 0 ;
while (h < t)
{
u = que[h++] ;
for(i = head[u] ; i != -1 ; i = e[i].next)
{
to = e[i].to ;
if(to != fa[u])
{
if(siz[son[u]] < siz[to]) son[u] = to ;
que[t++] = to ;
}
}
}
}
void BFS_cutLink(int rt, int tp){
int i, u, to, h = 0, t = 0 ;
que[t++] = rt ;
while (h < t)
{
u = que[h++] ;
w[u] = ++cnt ; top[u] = u ;
to = son[u] ;
while (to)
{
w[to] = ++cnt ; top[to] = u ;
for(i = head[to] ; i != -1 ; i = e[i].next)
if(e[i].to != fa[to] && e[i].to != son[to]) que[t ++] = e[i].to ;
to = son[to] ;
}
for(i = head[u] ; i != -1 ; i = e[i].next)
{
to = e[i].to ;
if(to != fa[u] && to != son[u]) que[t++] = to ;
}
}
}
3. 非直接合并查询:树上最长上升子序列
/*********************线段树成段更新最长上升子序列*************************/
void Up(int step){
L[step].lx = L[lson].lx + ( (L[lson].lx==L[lson].len && val[L[rson].left] > val[L[lson].right])?L[rson].lx:0) ;
L[step].rx = L[rson].rx + ((L[rson].rx==L[rson].len &&val[L[rson].left] > val[L[lson].right])?L[lson].rx:0) ;
L[step].mx = max(max(L[lson].mx,L[rson].mx),val[L[rson].left]
> val[L[lson].right]?(L[lson].rx+L[rson].lx):0);

L[step].dlx = L[lson].dlx + ( (L[lson].dlx == L[lson].len && val[L[rson].left] < val[L[lson].right]) ? L[rson].dlx : 0 );
L[step].drx = L[rson].drx + ((L[rson].drx == L[rson].len && val[L[rson].left] < val[L[lson].right]) ? L[lson].drx : 0 ) ;
L[step].dmx = max(max(L[lson].dmx,L[rson].dmx),val[L[rson].left]
< val[L[lson].right] ? (L[lson].drx+L[rson].dlx) : 0 ) ;
}
void build(int step,int l,int r){
L[step].left=l;
L[step].right=r;
L[step].len = r-l+1 ;
L[step].mid=(l+r)/2;
if(l==r)
{
L[step].lx = L[step].rx = L[step].mx = 1 ;
L[step].dlx =L[step].drx = L[step].dmx = 1 ;
return ;
}
…… ;
}
inline void unionNode(int l, int r, int ar ){
L[ar].lx = L[l].lx + ((L[l].lx==L[l].len && val[L[r].left]
> val[L[l].right]) ? L[r].lx : 0) ;
L[ar].rx = L[r].rx + ((L[r].rx==L[r].len && val[L[r].left]
> val[L[l].right]) ? L[l].rx : 0) ;
L[ar].mx = max(max(L[l].mx,L[r].mx),val[L[r].left]
> val[L[l].right]?(L[l].rx+L[r].lx):0);

L[ar].dlx = L[l].dlx + ((L[l].dlx == L[l].len && val[L[r].left]
< val[L[l].right]) ? L[r].dlx : 0 );
L[ar].drx = L[r].drx + ((L[r].drx == L[r].len && val[L[r].left]
< val[L[l].right]) ? L[l].drx : 0 ) ;
L[ar].dmx = max(max(L[l].dmx,L[r].dmx),val[L[r].left] < val[L[l].right]
? (L[l].drx+L[r].dlx) : 0 ) ;
L[ar].left = L[l].left ;
L[ar].right = L[r].right ;
L[ar].len = L[l].len + L[r].len ;
}
int query(int step,int l,int r){
if(l==L[step].left&&r==L[step].right) return step ;
…… ;
else    {
int lt = query(lson,l,L[step].mid);
int rt = query(rson,L[step].mid+1,r);
++scnt ;
unionNode(lt, rt, scnt) ;
return scnt ;
}
}
/*************************树链剖分*************************/
inline int unionAns(int l, int r){
int tmp = max(L[l].dmx, L[r].mx), ans ;
if(val[L[l].left] < val[L[r].left]) ans = L[r].lx + L[l].dlx ;
else ans = 0 ;
ans = max(tmp, ans) ;
return ans ;
}
int getAns(int u, int v){
if(u == v) return L[query(1, w[u], w[u])].mx ;
int tu = top[u], tv = top[v] ;
int ar, tr, ur, vr ;
scnt = 4*cnt +1;
ar = ++scnt ; ur = -1 ; vr = -1 ;
while (tu != tv)
{
if(dep[tu] > dep[tv])//calculate the link tu -> u.
{
tr = query(1, w[tu], w[u]) ;
if(ur == -1) ur = tr ;
else            {
++scnt ;
unionNode(tr, ur, scnt); //tr is left node.
ur = scnt ;
}
u = fa[tu] ; tu = top[u] ;
}
else        {
tr = query(1, w[tv], w[v]) ;
if(vr == -1) vr = tr ;
else            {
++scnt ;
unionNode(tr, vr, scnt) ; // tr is left node.
vr = scnt ;
}
v = fa[tv] ; tv = top[v] ;
}
}
if(dep[u] >= dep[v])// v is root.
{
tr = query(1, w[v], w[u]) ;
if(ur == -1) ur = tr ;
else        {
scnt ++ ;
unionNode(tr, ur, scnt) ;
ur = scnt ;
}
u = v ;
}
else    {
tr = query(1, w[u], w[v]) ;
if(vr == -1) vr = tr ;
else        {
++scnt ;
unionNode(tr, vr, scnt) ;
vr = scnt ;
}
v = u ;
}
if(ur == -1) return L[vr].mx ;
else if(vr == -1) return L[ur].dmx ;
return unionAns(ur, vr) ; // calculate the answer of u->v
}
4. 树上最大字段和
/*********************线段树最大子段和*************************/
inline void Up(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1] ;
lx[rt] = max(lx[rt<<1|1], lx[rt<<1] + sum[rt<<1|1]) ;
rx[rt] = max(rx[rt<<1], rx[rt<<1|1] + sum[rt<<1]) ;
mx[rt] = max(mx[rt<<1], mx[rt<<1|1]) ;//不合并
mx[rt] = max(mx[rt], lx[rt<<1] + rx[rt<<1|1]) ; //合并
}
inline void Down(int rt, int L, int R){
if(d[rt] != INF)
{
int x = d[rt] ;
int mid = (L+R) >> 1 ;
d[rt] = INF ;
d[rt<<1] = d[rt<<1|1] = x ;
sum[rt<<1] = (LL)x*(mid-L+1) ;
sum[rt<<1|1] = (LL)x*(R-mid) ;
lx[rt<<1] = rx[rt<<1] = mx[rt<<1] = x > 0 ? sum[rt<<1] : 0 ;
lx[rt<<1|1] = rx[rt<<1|1] = mx[rt<<1|1] = x > 0 ? sum[rt<<1|1] : 0 ;
}
}
inline void unionNode(int l, int r, int ar ){
sum[ar] = sum[l] + sum[r] ;
lx[ar] = max(lx[r], lx[l]+sum[r]) ;
rx[ar] = max(rx[l], rx[r]+sum[l]) ;
mx[ar] = max(mx[l], mx[r]) ;
mx[ar] = max(mx[ar], lx[l]+rx[r]) ;
}
void build(int rt, int l, int r){
d[rt] = INF ;
if(l == r)
{
sum[rt] = lx[rt] = rx[rt] = mx[rt] = val[l] ;
return ;
}
…… ;
}
void updata(int rt, int L, int R, int l, int r, int x){
if(L == l && r == R)
{
sum[rt] = (R-L+1)*x ;
lx[rt] = rx[rt] = mx[rt] = x > 0 ? sum[rt] : 0 ;
d[rt] = x ;
return ;
}
Down(rt, L, R) ;
…… ;
}
int query(int rt, int L, int R, int l, int r){
if(L == l && R == r) return rt ;
Down(rt, L, R) ;
…… ;
else    {
int x = query(rt<<1, L, mid, l, mid) ;
int y = query(rt<<1|1, mid+1, R, mid+1, r) ;
++scnt ;
unionNode(x, y, scnt) ;
return scnt ;
}
}
/*************************树链剖分*************************/
inline void unionAns(int x, int y, int ar){
mx[ar] = max(mx[x], mx[y]) ;
mx[ar] = max(mx[ar], rx[x]+rx[y]) ;
}
int getAns(int u, int v){
if(u == v) return query(1, 1, cnt, w[u], w[u]) ;
int tu = top[u], tv = top[v] ;
int ar, tr, ur, vr ;
scnt = 4*cnt +1;
ar = ++scnt ; ur = -1 ; vr = -1 ;
while (tu != tv)
{
if(dep[tu] > dep[tv])//calculate the link tu -> u.
{
tr = query(1, 1, cnt, w[tu], w[u]) ;
if(ur == -1) ur = tr ;
else            {
++scnt ;
unionNode(tr, ur, scnt); //tr is left node.
ur = scnt ;
}
u = fa[tu] ; tu = top[u] ;
}
else        {
tr = query(1, 1, cnt, w[tv], w[v]) ;
if(vr == -1) vr = tr ;
else            {
++scnt ;
unionNode(tr, vr, scnt) ; // tr is left node.
vr = scnt ;
}
v = fa[tv] ; tv = top[v] ;
}
}
if(dep[u] >= dep[v])
{
tr = query(1, 1, cnt, w[v], w[u]) ;
if(ur == -1) ur = tr ;
else        {
scnt ++ ;
unionNode(tr, ur, scnt) ;
ur = scnt ;
}
u = v ;
}
else    {
tr = query(1, 1, cnt, w[u], w[v]) ;
if(vr == -1) vr = tr ;
else        {
++scnt ;
unionNode(tr, vr, scnt) ;
vr = scnt ;
}
v = u ;
}
if(ur == -1) return vr ;
else if(vr == -1) return ur ;
unionAns(ur, vr, ar) ; // calculate the answer of u->v
return ar ;
}
四、持久化线段树
/*******************静态 Kth number ***************************************/
void build(int &rt, int l, int r ){
rt = ++tot ;
sum[rt] = 0 ;
if(l >= r) return ;
…… ;
}
void updata(int &rt, int pre, int l, int r, int i, int v){
rt = ++tot ;
ls[rt] = ls[pre] ; rs[rt] = rs[pre] ; sum[rt] = sum[pre] + v ;
if(l >= r ) return ;
int mid = l+r >> 1 ;
if(mid >= i ) updata(ls[rt], ls[pre], l, mid, i, v) ;
else updata(rs[rt], rs[pre], mid+1, r, i, v) ;
}
int query(int R, int L, int l, int r, int k){
if(l >= r) return l ;
int t = sum[ls[R]] - sum[ls[L]] ;
int mid = l+r >> 1 ;
if(t >= k) return query(ls[R], ls[L], l, mid, k) ;
else return query(rs[R], rs[L], mid+1, r, k-t) ;
}
/***************************************************************/
void solve(){
sort(ord+1, ord+1+n, comp) ;
cnt = rk[ord[1]] = 1 ;
nar[cnt] = ar[ord[1]] ;
for(i = 2 ; i <= n ; i ++)
{
if(ar[ord[i]] != ar[ord[i-1]])
{
rk[ord[i]] = ++cnt ;
nar[cnt] = ar[ord[i]] ;
}
else rk[ord[i]] = cnt ;
}
tot = 0 ;
build(T[0], 1, cnt) ;
for(i = 1 ; i <= n ; i ++) updata(T[i], T[i-1], 1, cnt, rk[i], 1) ;
for(i = 1 ; i <= m ; i ++)
{
scanf("%d %d %d", &l, &r, &k) ;
ans = query(T[r], T[l-1], 1, cnt, k) ;
printf("%d\n", nar[ans]) ;//离散后的数组
}
}
}
五、KD树
#define N 50005
#define MID(x,y) ( (x + y)>>1 )
using namespace std ;
typedef long long LL ;
struct Point{
int x[5];
LL dis;
Point(){
for(int i = 0 ; i < 5 ; i++) x[i] = 0 ;
dis = 9223372036854775807LL ;
}
friend bool operator < (const Point &a, const Point &b)
{ return a.dis < b.dis ; }
};
priority_queue <Point, vector<Point> > res ;
LL dist2(const Point &a, const Point &b, int k) {
//距离的平方,开根号很耗时,能不开就不开
LL ans = 0;
for (int i = 0; i < k; i++)
//一开始这儿写的i < 5,WA了N次。。。原本以为只要初始值设0就无所谓,
ans += (a.x[i] - b.x[i]) * (a.x[i] - b.x[i]);
//但发现Point有个全局变量,在多case下会出错。。。
return ans;
}
int ddiv;
bool cmpX(const Point &a, const Point &b){return a.x[ddiv] < b.x[ddiv];}
struct KDTree   {
Point p
;        //空间内的点
int Div
;
//记录区间是按什么方式划分(分割线平行于x轴还是y轴, ==1平行y轴切;==0平行x轴切)
int k;          //维数
int m;          //近邻
int getDiv(int l, int r)   {     //寻找区间跨度最大的划分方式
map <int, int> ms;
int minx[5],maxx[5];
for (int i = 0; i < k; i++)
{
ddiv = i;
minx[i] = min_element(p + l, p + r + 1, cmpX)->x[i];
maxx[i] = max_element(p + l, p + r + 1, cmpX)->x[i];
ms[maxx[i] - minx[i]] = i;
}
map <int ,int>::iterator pm = ms.end();
pm--;
return pm->second;
}
void build(int l, int r)  {      //记得先把p备份一下。
if (l > r)    return;
int mid = MID(l,r);
Div[mid] = getDiv(l,r);
ddiv = Div[mid];
nth_element(p + l, p + mid, p + r + 1, cmpX);
build(l, mid - 1);
build(mid + 1, r);
}
void findk(int l, int r, Point a) {//k(m)近邻,查找k近点的平方距离
if (l > r)    return;
int mid = MID(l,r);
LL dist = dist2(a, p[mid], k);
if (dist >= 0)
{
p[mid].dis = dist;
res.push(p[mid]);
while ((int)res.size() > m)
res.pop();
}
LL d = a.x[Div[mid]] - p[mid].x[Div[mid]];
int l1, l2, r1, r2;
l1 = l , l2 = mid + 1;
r1 = mid - 1, r2 = r;
if (d > 0)
swap(l1, l2), swap(r1, r2);
findk(l1, r1, a);
if ((int)res.size() < m || d*d < res.top().dis )
findk(l2, r2, a);
}
};
Point pp
;
KDTree kd;
int solve(){
for (int i = 0; i < n; i++)
for (int j = 0; j < kd.k; j++)
{
scanf("%d", &pp[i].x[j]);
kd.p[i] = pp[i];
}
kd.build(0, n - 1);
int t = 10 ;
while(t--)
{
Point a;
for (int i = 0; i < kd.k; i++)scanf("%d", &a.x[i]);
scanf("%d", &kd.m);
kd.findk(0, n - 1, a);
printf("the closest %d points are:\n", kd.m);
Point ans[11];
for (int i = 0; !res.empty(); i++)
{
ans[i] = res.top();
res.pop();
}
for (int i = kd.m - 1; i >= 0; i--)
{
for (int j = 0; j < kd.k - 1; j++)
printf("%d ", ans[i].x[j]);
printf("%d\n", ans[i].x[kd.k - 1]);
}
}
六、最远manhattan距离
int query(int rt, int p, int s) //维护每个状态的最大值、最小值。
void getTable(int pos){//每个点有sta个状态
int i, j, t ;
for(i = 0 ; i < sta ; i ++)
{
t = i ;
tmp[i] = 0 ;
for(j = 1 ; j <= k ; j ++)
{
if(t&1) tmp[i] += ar[pos].x[j] ;
else tmp[i] -= ar[pos].x[j] ;
t >>= 1 ;
}
}
}
int solve(){
sta = 1<<k ; //K维平面
build(1, 1, q) ;//将每个点的sta个状态插入树中
cnt = 0 ;
for(i = 1 ; i <= q ; i ++)
{
if(cnt < 2){puts("0") ;continue ; }
int ans = 0 ;
for(j = 0 ; j < sta ; j ++)
{
mxs = query(1, j, 1) ; //查询最大值;
mns = query(1, j, 0) ; //查询最小值;
ans = ans > mxs - mns ? ans : mxs-mns ;
}
printf("%d\n", ans) ;
}
七、LCA & RMQ & 树状数组
/*****************************LCA*******************************/
struct QNode{
int from, to, next, no ;
}qe[MAXN];
int cnt ;
int qhead[MAXN], pre[MAXN], LCA[MAXN] ;
inline void addQEdge(int a,int b,int c){
qe[++cnt].from = a ;
qe[cnt].to = b ;
qe[cnt].next = qhead[a] ;
qe[cnt].no = c ;
qhead[a] = cnt;
}
int find(int x){
if(x != pre[x]) pre[x]=find(pre[x]);
return pre[x];
}
void tarjan(int u){
int j, v ;
pre[u] = u ;
for(j = qhead[u] ; j != -1 ; j = qe[j].next)
{
v = qe[j].to;
LCA[qe[j].no] = find(v) ;
}
for(j = head[u] ; j != -1 ;j = e[j].next)
{
v = e[j].to ;
tarjan(v) ;
pre[v] = u ;
}
}
/*****************************RMQ*******************************/
int mn[MAXN][18] ;
void rmq_init(int num){
int i , j ;
for(j = 1 ; j <= num ; j ++ ) mn[j][0] = height[j] ;
int m = floor(log((double)num)/log(2.0)) ;
for(i = 1 ; i <= m ; i ++ )
{
for(j = num ; j > 0 ; j -- )
{
mn[j][i] = mn[j][i-1] ;
if(j+(1<<(i-1)) <= num)
mn[j][i] = min( mn[j][i] , mn[j+(1<<(i-1))][i-1]) ;
}
}
}
int rmq(int l,int r){
int m = floor(log((double)(r-l+1))/log(2.0)) ;
int a = min(mn[l][m], mn[r-(1<<m)+1][m] ) ;
return a ;
}
/*****************************树状数组*******************************/
int Lowbit(int t){ //求最小幂2^k
return t&(-t) ;
}
int Sum(int end) { //求前n项和
int sum = 0 ;
while(end > 0)
{
sum += c[end];
end -= Lowbit(end);
}
return sum;
}
void plus(int pos , int n, int num){ //对某个元素进行加法操作
while(pos <= n)
{
c[pos] += num;
pos += Lowbit(pos);
}
}
八、划分树
int SU[100001];
int U[21][100001];
int toL[21][100001];
int n,m,a,b,k,t;
inline int cmp(const void *a,const void *b){return *((int *)a) - *((int *)b) ;}
void buildtree(int l,int r,int d){
int i ;
if (l==r) return;
int mid = (l+r)>>1 , nowl = l , nowr = mid+1 , midtol = 0 ;
for (i = mid ;i>=l  &&   SU[i] == SU[mid] ; i--) ++midtol ;
for (i = l ; i <= r ; i++)
{
toL[d][i] = i==l ? 0 : toL[d][i-1];
if (U[d][i] < SU[mid])
{
U[d+1][nowl++] = U[d][i];
++toL[d][i];
}
else if (U[d][i]==SU[mid] && midtol)
{
U[d+1][nowl++] = U[d][i];
++toL[d][i];
--midtol;
}
else U[d+1][nowr++] = U[d][i];
}
buildtree(l,mid,d+1);
buildtree(mid+1,r,d+1);
}
int answer(int a,int b,int k){
int l = 1,r = n,d = 0;
int ls,rs,mid;
while (a != b)
{
ls = a==l ? 0 : toL[d][a-1];
rs = toL[d][b];
mid = (l+r)>>1;
if (k <= rs - ls)
{
a = l+ls;
b = l+rs-1;
r = mid;
}
else        {
a = mid+1+a-l-ls;
b = mid+1+b-l-rs;
k -= rs-ls;
l = mid+1;
}
++d;
}
return U[d][a];
}
int solve(){
for (i=1;i<=n;i++)
{
scanf("%d",&t);
SU[i]=U[0][i]=t;
}
sort(SU+1, SU+1+n) ;
buildtree(1 , n , 0 );
printf("%d\n",answer(a, b, k ) );
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: