YbtOJ 752 最優分組

2022-06-13 13:54:09 字數 2116 閱讀 2580

首先我們忽略 \(c\) 的限制,如果只考慮 \(d\) 的話,不難發現以第 \(i\) 個人結尾分組,左端點是一段連續的區間 \([lft_i,i)\)。 可以用 st 表預處理區間最小值然後雙指標掃一遍求出 \(lft\)。

加入了 \(c\) 的限制之後,此時和每乙個點能轉移過來的位置就不是連續的區間了。考慮對於當前區間內 \(c\) 的最大值分治,也就是建出笛卡爾樹然後按照深度優先遍歷進行轉移。

設區間 \([l,r]\),最大值所在位置為 \(mid\),先遞迴處理 \([l,mid)\),然後求 \([l,mid)\) 對 \([mid,r]\) 的貢獻。考慮三種情況:

\(lft_i\leq l\) 且 \(i\geq mid+c_\)

這一段顯然可以被 \([l,mid)\) 全部貢獻到,直接線段樹區間查詢,再區間賦值即可。

\(l因為每乙個點指揮在這樣的情況一次,所以直接暴力線段樹區間詢問即可。

到葉子節點之後在 \(f\) 和線段樹上取一下最優即可。

時間複雜度 \(o(n\log n)\)。

#include #define mp make_pair

using namespace std;

const int n=1000010,lg=20,mod=1e9+7;

int n,c[n],d[n],lft[n],lg[n],st[n][lg+1];

int read()

void buildst()

; }

}f[n];

struct segtree

void pushdown(int x)

; } }

void update(int x,int l,int r,int ql,int qr,node v)

pushdown(x);

int mid=(l+r)>>1;

if (ql<=mid) update(x*2,l,mid,ql,qr,v);

if (qr>mid) update(x*2+1,mid+1,r,ql,qr,v);

pushup(x); }

node query(int x,int l,int r,int ql,int qr)

; if (ql<=l && qr>=r) return val[x];

pushdown(x);

int mid=(l+r)>>1; node res=(node);

if (ql<=mid) res=res+query(x*2,l,mid,ql,qr);

if (qr>mid) res=res+query(x*2+1,mid+1,r,ql,qr);

return res;

}}seg;

void solve(int l,int r)

int mid=getmin(l+1,r);

solve(l,mid-1);

int ll=mid,rr=r,mm,pos;

while (ll<=rr)

pos=ll-1;

// part 1

node res=seg.query(1,0,n,l,max(mid-c[mid],l));

for (int i=max(mid,l+c[mid]);i<=pos;i++)

// part 2

res=seg.query(1,0,n,l,mid-1);

seg.update(1,0,n,mid+c[mid],pos,res);

// part 3

for (int i=pos+1;i<=r;i++)

solve(mid,r);

}int main()

for (int i=1;i<=n;i++) d[i]=n-c[i]+1;

buildst();

f[0]=(node);

solve(0,n);

if (f[n].c) printf("%d %d",f[n].v-1,f[n].c);

else printf("-1");

return 0;

}

YbtOJ 752 最優分組 笛卡爾樹,線段樹

n 個人,每個人有 c i 和 d i 分別表示這個人所在的隊伍的最少 最多人數。然後要求將這些人分成編號連續的若干隊使得隊伍最多,並且求分隊方案數。1 leq n leq 10 6 陰間題目.為了方便計算先定義乙個結構體 包含答案和方案數 和加法運算表示取最大值 相同加方案數作為答案。設 f i ...

YbtOj練習 貪心3 最優密碼

這道題暴力拿了90分,正解實在不會寫!因為字串不好操作,所以乾脆把它變成乙個int的陣列,最後輸出時直接把數字轉換成字元輸出。首先考慮我們的貪心策略 下標從1開始 設k為我們已經處理過的位置的個數,初始時k 0。只要我們的操作次數還有剩餘,那麼就考慮第k 1個位置能通過交換操作得到的最小的數字是多少...

ybtoj 二分演算法 最小時間

有n個物品,第i個物品有兩個屬性k,b,表示它在時刻 的價值為k x b。當前處於時刻0,你可以選擇不超過m個物品,使得存在非負整數時刻t,你選擇的所有物品的總價值大於等於s。給出s,求t的最小值。第一行三個整數n,m,s。接下來n行,第i行兩個整數k,b。一行乙個整數表示答案。3 2 100 3 ...