一道splay綜合大板子題。
題面:下面是題解:
首先對每個點維護這些量:
1.兩個兒子(ch[2])
2.父節點(fa)
3.當前點權值(vl)和子樹權值(sum)
4.修改標記(xg),反轉標記(fz)。
5.mx,mxl,mxr(不清楚的建議做小白逛公園)。
題中還有乙個條件,即:
100%的資料中,任何時刻數列中最多含有500 000個數。
這就解決了空間問題。我們可以用乙個佇列記錄有多少點可以**,這樣就可以節省大量的空間。
最後一點:本題中涉及到max值,區間反轉後需要update。
**:
#include#include#include
using
namespace
std;
#define n 1000050
intn,m,a[n],rt,tot,pos,cnt,id[n];
queue
que;
char ch[15
];struct
splay
tr[n];
void update(int
u)void pushdown(int
u)else
}if(tr[u].fz)
}void rotate(int
x)void splay(int u,int
goal)
if(!goal)rt=u;
}void build(int l,int r,int
f)else
tr[u].vl =a[mid];
tr[u].fa =fa;
update(u);
tr[fa].ch[mid>=f] =u;
}int find(int x,int
k)void insert(int k,int
tt)
for(int i=1;i<=tt;i++)
else
}build(
1,tt,0
);
int rt0 = id[(1+tt)>>1
];
int l = find(rt,k+1
);
int r = find(rt,k+2
); splay(l,0);
splay(r,l);
tr[r].ch[
0]=rt0;
tr[rt0].fa=r;
update(r);
update(rt);
}void rip(int
x)int deal(int l,int
r)void erase(int l,int
r)void make_same(int l,int r,int
k)void rever(int l,intr)}
int get_sum(int l,int
r)int
main()
else
if(ch[0]=='d'
)
else
if(ch[2]=='k'
)
else
if(ch[0]=='r'
)
else
if(ch[0]=='g'
)
else
}return0;
}
noi2005維護數列
請寫乙個程式,要求維護乙個數列,支援以下 6 種操作 請注意,格式欄 中的下劃線 表示實際輸入檔案中的空格 操作編號 輸入檔案中的格式 說明1.插入 insert posi tot c1 c2 c tot 在當前數列的第 posi 個數字後插入 tot 個數字 c1,c2,c tot 若在數列首插 ...
NOI2005 維護數列
陳年老題。我就 碼了4k多。主要就是用splay,然後處理區間上的東西 區間反轉就和模板一樣,但是要記得反轉leftmax和rightmax 區間賦值就把那個區間提取出來,然後給子樹根打個same標記,表示下面的全一樣。區間求最大子段和就和線段樹的套路一樣。區間插入就先弄好一顆平衡樹,然後把原平衡樹...
NOI2005 維護數列
傳送門 我還是沒有逃過在這道題上debug好久的命運 我是使用 fhq treap 來做的這道題。寫的時候寫的挺爽的 調的時候真難受。首先我們先來說說咋做吧。前5個操作對於 fhq treap 來說不在話下,只要多打兩個標記就可以了。但是如何求最大子段和?於是乎我們再打三個標記來維護它 霧 然後我們...