BZOJ 1500 洛谷2042維護序列題解

2022-05-20 12:13:11 字數 1822 閱讀 9938

bz鏈結

洛谷鏈結

這道題真是喪心病狂。。。。

應該很容易就可以看出做法,但是寫**寫的.......

思路很簡單,用乙個平衡樹維護一下所有的操作就好了,重點講解一下**的細節

首先如果按照常規寫法的話,splay的節點要開到4000000,

直接炸飛,

由於任意時刻splay中的節點最多只有500000個,我們只需要開500000個節點就好了

然後將沒有用的節點**起來,下一次插入是插入到這些節點中

然後就是插入是將要插入的所有數字build成一顆平衡樹,直接接在要插入的位置,這樣會快很多

維護最大子段和與線段樹維護最大子段和方法一樣,維護以包含左端點且以左端點開頭的最大欄位和,以及以右端點結尾的最大欄位和

還有自身的最大子段和,然後就可以通過左右兒子的資訊快速算出當前節點的資訊了

具體細節可以看**

# include# include

# include

# include

# include

# include

using

namespace

std;

const

int inf = 0xfffffff

;const

int mn = 500005

;int

n,m,a[mn];

struct

splay

void pushdown(int

x)

else

}if(rev[x])

}void rotate(int x,int &k)

son[y][tmp^1]=son[x][tmp],fa[son[y][tmp^1]]=y;

son[x][tmp]=y;

fa[y]=x,fa[x]=z;

updown(y),updown(x);

}void splay(int x,int &k)

rotate(x,k);}}

int find(int x,int

rk)

int split(int k,int

tot)

void recyc(int

x)

void

update()

void

rever()

}void build(int l,int r,int

f)

if(l1

,mid);

if(r>mid) build(mid+1

,r,mid);

v[now]=a[mid];

fa[now]=pre;

updown(now);

son[pre][(mid>=f)]=now;

}void

ins()

else id[i]=++cnt;

build(

1,tot,0);//

將要加入的數字建一顆splay

int z=id[(1+tot)>>1];//

取根int x=find(root,k+1),y=find(root,k+2

); splay(x,root),splay(y,son[x][

1]);

fa[z]=y;

son[y][

0]=z;

updown(y),updown(x);

}void

del()

void

query()

} t;

intmain()

return0;

}

BZOJ 1500, 維修數列

傳送門 編寫乙個支援插入 刪除 修改 翻轉 求和以及求和最大子串行的資料結構。splay無疑。但是寫太醜也是會tle的,比方說插入的時候應該以建樹的形式插入,而不是乙個點乙個點的形式。實現起來要注意的細節很多,對練習打splay挺有好處。陸陸續續除錯了好多天,總算在崩潰之前ac了 include c...

BZOJ 1500 維修數列

time limit 10 sec memory limit 64 mb submit 14433 solved 4701 submit status discuss 輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初...

bzoj 1500 維修數列

輸入的第1 行包含兩個數n 和m m 20 000 n 表示初始時數列中數的個數,m表示要進行的運算元目。第2行包含n個數字,描述初始時的數列。以下m行,每行一條命令,格式參見問題描述中的 任何時刻數列中最多含有500 000個數,數列中任何乙個數字均在 1 000,1 000 內。插入的數字總數不...