ROI 2018 Day 2 無進製加法

2022-05-20 04:52:24 字數 2795 閱讀 2816

題目大意:

給出二進位制數\(a_1,\ldots a_n\),對於\(b_1\ldots b_n\)

滿足\(a_i\leq b_i\),\(\bigoplus b_i=\sum b_i\),其中$\bigoplus $為異或和

求\(\sum b_i\)最小值

設長度量級為\(n=\sum len(a_i)\)

列舉當前位為0,下面的位為1,貪心確定是否存在方案

檢查乙個答案是否合法:

動態維護乙個倒序的\(a_i\)集合,從高到低考慮每乙個位置

1.如果當前位為0:

如果\(a_i\)中存在大於等於這一位的數,非法

2.如果當前位為1:

2-1.如果\(a_i\)中存在2個當前位為1的數,非法

2-2.如果\(a_i\)中存在恰好乙個,則將這個1用於這個\(a_i\),並將\(a_i\)去掉最高位後放回集合

2-3.不存在,用這個\(1\)刪除最大的乙個\(a_i\)

實際看來,這個貪心本身效率並不高

\[\

\]令\(b=\max\\)

則\(len(ans)\in[b,b+1]\)

上下界均可以由上面的貪心模擬得到

\[\

\]顯然在不斷更改的過程中,當前的\(a_i\)一定是原先的某乙個\(a_i\)的一段字尾

考慮將所有這樣的字尾排序,為了方便,用每乙個最高的1來表示乙個合法的字尾

顯然可以先按照字尾長度分類,同長度的字尾,按照字尾中下乙個1出現的位置排序

也就是乙個類似基數排序個過程,額外維護每乙個字尾中下乙個出現的\(1\)所對應的字尾即可

預處理複雜度為\(o(n\log n)\)

同時,也可以用線段樹快速維護插入/刪除的排名,得到\(b\)的值,單次操作複雜度\(o(\log n)\)

\[\

\]稱滿足\(len(a_i)+i-1=b\)的\(i\)為\(\text\)

令\(p\)為最小的\(\text\),也就是在貪心過程中第乙個出現情況2-1./2-2.的位置

決策答案為\(b\)還是為\(b+1\),也就是決策

是用\(len(a_p)\)這個位置刪除\(a_p\)的最高位,還是用\(len(a_p)+1\)的位置刪除\(a_p\)

(\([1,p-1]\)的部分一定會被刪掉)

\(\text\)採用暴力遞迴來完成確定每一位的這個操作

function solve(limit) limit為當前可以使用的最高位的1

求得 b,p

刪除 a[1,p-1]

刪除 a[p]最高位

if b<=limit and solve(p-1) then

ans[len(a[p]),b]=1

return true

刪除a[p]

if b+1<=limit and solve(p) then

ans[len(a[p])+1,b+1]=1

return true

else return false

end

至於複雜度,官方題解給出為\(o(n)\)次遞迴和刪除/加入操作,最終複雜度為\(o(n\log n)\)

#includeusing namespace std;

#define pb push_back

#define rep(i,a,b) for(int i=a,i##end=b;i<=i##end;++i)

#define drep(i,a,b) for(int i=a,i##end=b;i>=i##end;--i)

template inline void cmin(t &a,const t &b)

template inline void cmax(t &a,const t &b)

void upd(int p,int l,int r,int ql,int qr,int x)

down(p);

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

if(ql<=mid) upd(p<<1,l,mid,ql,qr,x);

if(qr>mid) upd(p<<1|1,mid+1,r,ql,qr,x);

s[p]=max(s[p<<1],s[p<<1|1]);

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

void add(int x,int k)

// find the first critical position "p", and return all the bits in [1,p]

void get(int p,int l,int r,int x,v &r)

} t;

int solve(int l)

// try ans b+1 , so we use bit [nxt+1,b+1] to delete the [1,p]

if(nxt[p]) t.add(nxt[p],-1);

if(bfor(int i:r) t.add(i,1);

return 0;

}int main()

} rk[0]=1e9;

int k=m;

rep(i,0,l-1) );

for(int j:a[i]) id[rk[j]=++k]=j;

k-=a[i].size();

} t.build(1,1,m);

rep(i,1,n) t.add(fir[i],1);

memset(s,0,sizeof s);

drep(i,solve(inf)-1,0) putchar(s[i]^48);

}

NOIP2018 Day2毒瘤題目

拿到題目,一看,圖論,完了.仔細看了看題目,誒這個不是dfs序麼?當場敲出dfs。跑樣例一,過了,結果一跑樣例二,當場廢掉。樣例二有環,會跑不出正解 不知道我的dfs能不能過樹形圖 又手造資料卡死自己的日常 涼掉了.後面仔細想想 好像可以跑乙個最小生成樹?於是開心的打了乙個 color 看起來沒問題...

HEOI 2018 Day2 T2 林克卡特樹

給乙個n個節點的樹,然後將其分成k 1個聯通塊,再在每個聯通塊取一條路徑,將其連線起來,求連線起來的路徑最大權值。考場只會20分,還都打掛了 60分的做法其實並不難,nk dp即可,設 f i,j,0 1 2 表示i子樹選取了j個聯通塊,i這個節點連了0 1 2條邊時的最優解。100分的做法就是60...

NOIP2018 Day2 T1 旅行 題解

乍一看,一道基環樹。說實話考場上有點懵,day2t1直接上基環樹?再一看,好像只是一道無腦的搜尋加剪枝 對於noip資料範圍,o n 2 是可以可過去的 但是對於那個加強版資料,可能需要乙個筆者不會的超級玄學。好吧不扯了,咱們來看看資料範圍。m n 1的情況比較簡單只需一遍跑一邊搜尋,每次找字典序最...