細節巨多……多的狗死人了……
首先我們要建出一棵線段樹,這棵線段樹要存放以下幾個東西:最長區間,起點,終點,最長字首,字首終點,最長字尾,字尾起點。(所以維護打了足足六十行……查詢打了三十行……)
如何查詢呢?最長序列無外乎三種情況:
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 #include5cogs775using
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()
.
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...