cogs775 山海經 線段樹

2022-03-27 02:51:29 字數 2013 閱讀 9190

細節巨多……多的狗死人了……

首先我們要建出一棵線段樹,這棵線段樹要存放以下幾個東西:最長區間,起點,終點,最長字首,字首終點,最長字尾,字尾起點。(所以維護打了足足六十行……查詢打了三十行……)

如何查詢呢?最長序列無外乎三種情況:

1、全在左子樹中。我們設$len[i]$為$i$節點最長序列,則此時$len[i]=len[i<<1]$;

2、全在右子樹中,同理可以得出$len[i]=len[i<<1|1]$。

3、橫跨兩個子樹。設字首長為$pre[i]$,字尾長為$suf[i]$,那麼$len[i]=suf[i<<1]+pre[i<<1|1]$。

維護時順帶按照長度第一字典序第二要求維護區間起終點即可。

查詢時按照相同方法進行查詢,需要注意的是,最後一次合併時左右可能並未完全更新,上傳完成後還要再找一次最優解。

1 #include2 #include3 #include4 #include5

using

namespace

std;

6const

int maxn=100005,inf=0x3f3f3f3f;7

struct

node

814 }segtree[maxn<<2

];15

#define mid ((l+r)>>1)

16#define lc root<<1

17#define rc root<<1|1

18#define lson lc,l,mid

19#define rson rc,mid+1,r

20void pushup(int

root)

2128

else

2933

if(segtree[rc].rmaxsegtree[lc].rmax)

3438

else

3943

if(segtree[lc].totmax

4451

else

5257}58

else

if(segtree[lc].totmaxsegtree[rc].lmax)

5964

else

if(segtree[lc].totmax==segtree[lc].rmax+segtree[rc].lmax)

6572

else

7377}78

else

7984}85

void cmp(node x,node y,node &z)

8693

else z.lmax=x.lmax,z.pre=x.pre;

94if(y.rmaxx.rmax)

9599

else

100104

if(x.totmax

105112

else

113118

}119

else

if(x.totmaxy.lmax)

120125

else

if(x.totmax==x.rmax+y.lmax)

126131

else z.totmax=x.totmax,z.st=x.st,z.en=x.en;

132}

133void build(int root,int l,int

r)134

143build(lson),build(rson);

144pushup(root);

145}

146#undef mid

147void

print(node t)

148155 node query(int root,int l,int

r)156

164int

n,q;

165int

haha()

166177

}178

int sb=haha();

179int main()

cogs775

.

77 開燈問題

時間限制 3000 ms 記憶體限制 65535 kb 難度 1 描述 有n盞燈,編號為1 n,第1個人把所有燈開啟,第2個人按下所有編號為2 的倍數的開關 這些燈將被關掉 第3 個人按下所有編號為3的倍數的開關 其中關掉的燈將被開啟,開著的燈將被關閉 依此類推。一共有k個人,問最後有哪些燈開著?輸...

77 火車進站

題目描述 給定乙個正整數n代表火車數量,0輸出描述 輸出以字典序從小到大排序的火車出站序列號,每個編號以空格隔開,每個輸出序列換行,具體見sample。示例1輸入 31 2 3 輸出1 2 3 1 3 2 2 1 3 2 3 1 3 2 1 此處所謂字典序排序的意思是這n輛火車有多少種出站的可能順序...

7 7 古風排版

中國的古人寫文字,是從右向左豎向排版的。本題就請你編寫程式,把一段文字按古風排版。輸入在第一行給出乙個正整數n 100 是每一列的字元數。第二行給出乙個長度不超過1000的非空字串,以回車結束。按古風格式排版給定的字串,每列n個字元 除了最後一列可能不足n個 4this is a test case...