Ynoi2015 世上最幸福的女孩

2022-03-25 22:28:57 字數 3225 閱讀 7530

link

先考慮單點修改的做法:

線段樹上每個節點維護四個資訊:\(sum,pre,suf,ans\)。分別代表區間和,區間最大字首和,區間最大字尾和,區間最大子段和。

合併:\(sum_x=sum_l+sum_r\)

\(pre_x=\max(pre_l,sum_l+pre_r)\)

\(suf_x=\max(suf_r,sum_r+suf_l)\)

\(ans_x=\max(\max(ans_l,ans_r),suf_l+pre_r)\)

考慮如何將修改擴充套件到全域性修改。

假如全域性已經被加上了\(tag\),現在希望求某個點的新的\(sum,pre,suf,ans\)。

\(sum\)非常簡單就不講了。

\(pre\)和\(suf\)具有對稱性,只考慮\(pre\)。

如果將\((x,pre_x)\)看做乙個點(\(pre_x\)表示長度為\(x\)的字首和),那麼我們就是要求\(tag*x+y\)的最大值。

維護乙個凸包,查詢的時候二分一下。

pushup就是將\(pre_\)平移\((len_,sum_)\)之後和\(pre_\)接起來。

現在看\(ans\),在單點修改的部分\(ans\)是與左右兒子的\(ans,suf,pre\)掛鉤的,所以我們類似地考慮。

將\((x,ans_x)\)看做乙個點(\(ans_x\)表示長度為\(x\)的最大子段和),那麼我們就是要求\(tag*x+y\)的最大值。

還是維護乙個凸包,查詢的時候二分一下。

pushup稍微麻煩一點,首先我們合併\(ans_,ans_\),然後求出\(suf_,pre_\)的mincowsky和,再將這兩個凸包合併。

這樣我們可以在一開始建出一棵每個節點維護了\(pre,suf,ans\)三個凸包的線段樹,每次詢問在\(\log\)個節點上二分出最優的\(pre,suf,ans\)然後再按subtask 2的做法合併。這樣子的時間複雜度是\(o(n\log n+m\log^2n)\)的。

我們可以將所有詢問離線之後按\(tag\)排序,這樣凸包上指標的移動就是單調的,因此時間複雜度是\(o((n+m)\log n)\)。

#include#include#includeusing std::sort;

using ll=long long;

namespace io

void flush()

void put(char x)

int read()

void write(ll x)

}using io::read;using io::write;

const int n=300007,m=600007;const ll inf=1ll<<50;

ll max(const ll&a,const ll&b)

int n,m,cnt;ll tag,a[n],ans[m];

struct dot;

dot operator+(const dot&a,const dot&b);}

dot operator-(const dot&a,const dot&b);}

int operator<(const dot&a,const dot&b)

struct convex

void upd(const dot&a)

void ins(const dot&a)

void clr(const int&n);top=n;}

void build()

}ll cal()

};struct data;

data operator+(const data&a,const data&b);}

namespace segtree

void merge(convex&c,convex&a,convex&b,const dot&p)

void merge(convex&c,convex&a,convex&b)

void build(int p,int l,int r,int d)

,pre[p][1]=suf[p][1]=ans[p][1]=,pre[p].top=suf[p].top=ans[p].top=2;

else

),merge(suf[p],suf[rs],suf[ls],),++ans[p].stk,ans[p].clr(r-l);

for(int i=1;i<=ans[ls].top;++i) ans[p].upd(ans[ls][i]);

for(int i=1;i<=ans[rs].top;++i) ans[p].upd(ans[rs][i]);

merge(ans[p],suf[ls],pre[rs]),--ans[p].stk,ans[p][1]=,++ans[p].top,ans[p].build();

} pre[p].now=suf[p].now=ans[p].now=1,ppre[d]=pre[p].stk+pre[p].top,psuf[d]=suf[p].stk+suf[p].top,pans[d]=ans[p].stk+ans[p].top;

}data query(int p,int l,int r,int l,int r)

;if(r<=mid) return query(ls,l,mid,l,r);

if(l>=mid) return query(rs,mid,r,l,r);

return query(ls,l,mid,l,mid)+query(rs,mid,r,mid,r);

}#undef ls

#undef rs

#undef mid

}struct queryq[m];

int operator<(const query&a,const query&b)

int main()

,0ll);

sort(q+1,q+cnt+1),tag=q[1].tag;

for(int i=1;i<=cnt;++i) q[i].tag-=tag;

for(int i=1;i<=n;++i) a[i]+=tag;

segtree::init(),segtree::build(1,0,n,0);

for(int i=1;i<=cnt;++i) tag=q[i].tag,ans[q[i].id]=segtree::query(1,0,n,q[i].l-1,q[i].r).ans;

for(int i=1;i<=cnt;++i) write(ans[i]);

return io::flush(),0;

}

P5071 Ynoi2015 此時此刻的光輝

傳送門 lxl大毒瘤 首先乙個數的因子個數就是這個數的每個質因子的次數 1的積,然後考慮把每個數分解質因子,用莫隊維護,然後我交上去就0分了 如果是上面那樣的話,我們每一次移動指標的時間複雜度是o 這個數的質因子個數 再加上我人傻常數大,t很正常 於是按照memset0的說法,可以預處理質因子的字首...

洛谷 P5072 Ynoi2015 盼君勿忘

給定乙個序列,每次查詢乙個區間 l,r 中所有子串行分別去重後的和mod p 我們考慮每個數的貢獻。即該區間內含有這個數的子串行個數。用補集轉化為不含這個數的子串行個數。那麼,假設這個數在 l,r 內出現了k次,則一共有2 r l 1 2 r l 1 k 個子序列包含這個數。本題可以離線,因此選擇使...

CEOI2015 Day2 世界冰球錦標賽

題目描述 譯自 ceoi2015 day2 t1 ice hockey world championship 今年的世界冰球錦標賽在捷克舉行。bobek 已經抵達布拉格,他不是任何團隊的粉絲,也沒有時間觀念。他只是單純的想去看幾場比賽。如果他有足夠的錢,他會去看所有的比賽。不幸的是,他的財產十分有限...