bzoj2333 SCOI2011 棘手的操作

2022-08-20 11:57:08 字數 1646 閱讀 3927

bzoj2333

聯通塊合後並不需要再拆開,可以考慮離線做法

想辦法將各個點按聯通塊有序排列,接下來就直接用線段樹區間維護即可

fa[i] 記錄 i 所處聯通塊的起始點

ed[i] 記錄以i為起始點的聯通塊的終止點

nt[i] 記錄 i 的下乙個節點

#include using namespace std;

const int n = 300005;

int n, q, a[n];

int dfn[n], w[n], t;

int fa[n], nt[n], ed[n];

inline int read()

while(ch >= '0' && ch <= '9')

return x * f;

}struct node

q[n];

struct tree

t[n << 3];

int findf(int x)

void init()

else if(s[0] == 'a')

else if(s[1] == '2')

else

}else

else if(s[1] == '2')

else q[i].op = 7;}}

}void get_id()

}}void pushup(int p)

void pushdown(int p)

void build(int p, int x, int y)

int mid = (x + y) >> 1;

build(p << 1, x, mid); build(p << 1 | 1, mid + 1, y);

pushup(p);

}void update(int p, int x, int y, int v)

pushdown(p);

int mid = (pl + pr) >> 1;

if(y <= mid) update(p << 1, x, y, v);

else if(x > mid) update(p << 1 | 1, x, y, v);

else

pushup(p);

}int query_max(int p, int x, int y)

void solve()

else if(q[i].op == 2) update(1, dfn[x], dfn[x], y);

else if(q[i].op == 3) update(1, dfn[findf(x)], dfn[ed[findf(x)]], y);

else if(q[i].op == 4) update(1, 1, n, x);

else if(q[i].op == 5) printf("%d\n", query_max(1, dfn[x], dfn[x]));

else if(q[i].op == 6) printf("%d\n", query_max(1, dfn[findf(x)], dfn[ed[findf(x)]]));

else printf("%d\n", query_max(1, 1, n));

}}int main()

bzoj2333 SCOI2011 棘手的操作

全抄hzwer的 但是有幾個點還是說一下 首先,如果兩個點已經在乙個堆裡面了,再合併會出現環 這個很顯然把,但是你會忘了寫 其次,系統棧會炸 include include include include using namespace std multisetst struct heapq 300...

bzoj2333 SCOI2011 棘手的操作

可以大力寫乙個平衡樹啟發式合併,除了每個連通塊維護乙個平衡樹再對全域性維護乙個平衡樹,每個節點表示某乙個連通塊的最大值.我的常數比較大,危險地卡過去了.include include include using namespace std const int maxn 300005 struct n...

bzoj2333 SCOI2011 棘手的操作

題目鏈結 n個節點維護一些操作。我們用可並大根堆進行維護。對於每個連通塊建乙個區域性可並堆,因為要詢問全域性最大值,所以還要對全域性建乙個全域性可並堆記錄之前區域性可並堆堆頂元素。u 合併x所在的堆以及y所在的堆,並在全域性堆中刪除合併前的區域性堆堆頂元素,因為它合併以後已經不是其連通塊的堆頂了。a...