2019牛客暑期多校 第四場 寫題記錄

2021-09-25 15:33:52 字數 4821 閱讀 5569

給了些關鍵點 在一棵樹上 選取乙個點讓他們相聚 時間最短

其實就是求樹直徑 不過這次dfs完 我們找最遠點的時候只看標記點 第二次dfs完也一樣

#include

using namespace std;

const

int maxn =

1e5+5;

int n, m, cnt;

int head[maxn]

, d[maxn]

;int to[maxn <<1]

, nxt[maxn <<1]

;bool v[maxn]

;void

ade(

int a,

int b)

void

dfs(

int x,

int pre)

}int

main()

for(

int i =

1, a; i <= m; i ++

) cin >> a, v[a]=1

; d[1]

=0,dfs(1

,-1)

;int rt =-1

, tmp =-1

, ans =-1

;for

(int i =

1; i <= n; i++)if

(v[i]

&& d[i]

> tmp)

d[rt]=0

,dfs

(rt,-1

);for(

int i =

1; i <= n; i ++)if

(v[i]

&& d[i]

> ans)

ans = d[i]

; cout <<

(ans +1)

/2<< endl;

return0;

}

on 是什麼做法啊orz

給你乙個長度n的序列 選取乙個數字 和b包含它區間(而且它必須是這個區間的最小值) 使a[i]*(這一區間的和) 最大

首先單調棧 處理每個a[ i ] 管理區間(沒有比它小的最大連續區間)

然後 對 a[ i ] 分2種情況 正負來考慮

大於 0 的情況 顯然是 它 管理的區間和 *a[ i ] 因為a[i]>0 同時它肯定是這區間最低點 該區間越長和越大

小於 0 的情況 不妨我們維護乙個 字首和 既然它是負數 我們 當前i 到r[ i ]字首和最好越小越好 而l[ i ] 到 i得和越大越好

#include

#define fastio ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)

//#define int long long

using namespace std;

typedef

long

long ll;

const

long

long inf =

0x3f3f3f3f3f3f3f3f

;const

int maxn =

3e6+5;

int n;

ll a[maxn]

,sum[maxn]

, b[maxn]

;int l[maxn]

,r[maxn]

;struct node tr[maxn<<2]

;void

pushup

(int rt)

void

build

(int l,

int r,

int rt)

;return;}

int mid=

(l+r)

>>1;

build

(l,mid,rt<<1)

;build

(mid+

1,r,rt<<1|

1);pushup

(rt);}

ll maxquery

(int l,

int r,

int l,

int r,

int rt)

int mid=

(l+r)

>>1;

ll res=

-inf;

if(l<=mid) res=

max(res,

maxquery

(l,r,l,mid,rt<<1)

);if(r>mid) res=

max(res,

maxquery

(l,r,mid+

1,r,rt<<1|

1));

return res;}

ll minquery

(int l,

int r,

int l,

int r,

int rt)

int mid=

(l+r)

>>1;

ll res=inf;

if(l<=mid) res=

min(res,

minquery

(l,r,l,mid,rt<<1)

);if(r>mid) res=

min(res,

minquery

(l,r,mid+

1,r,rt<<1|

1));

return res;

}void

sollr()

while

(!s.

empty()

) s.

pop();

for(

int i=n; i>=

1; i--)}

signed

main()

else

}printf

("%lld\n"

,ans)

;return0;

}

d triples i

把這個資料拆成 21212121 的樣子

n % 3 == 0 直接輸出

n % 3 == 1 我們考慮 如果 補 1 夠 2個 我們直接 n - b[1] n - b[0];

如果 二進位制中貢獻 1 的只有乙個 我們選擇 b[0] + c[0] 和 n - b[0];

else 我們選擇 用 2位置補成3倍數 c[0] + c[1] + c[2] 和 n - c[0] - c[1];

n % 3 == 2 與上面相反

#include

typedef

long

long ll;

using namespace std;

vector b, c;

intmain()

else

x <<=1;

}if(n %3==

1)else}}

return0;

}

j free

老題 分層圖dj水過

#include

#define a first

#define b second

using namespace std;

const

int maxn =

1e3+10;

int head[maxn]

, cnt;

int nxt[maxn <<1]

, d[maxn <<1]

, to[maxn <<1]

;int n, m, s, t, k;

void

ade(

int a,

int b,

int c)

typedef pair<

int,

int> p;

typedef pair<

int, pair<

int,

int>> pp;

priority_queue

,greater

> que;

int dis[maxn]

[maxn]

;bool vis[maxn]

[maxn]

;voiddj(

)if(u.b < k && dis[v]

[u.b +1]

> dis[u.a]

[u.b])}

}}signed

main()

dj();

cout << dis[t]

[k]<< endl;

return0;

}

k number

比如說 123400

我們先統計單個0

ans += 2;

然後字首和 123400

#… .% 3後 100111

我們可以整除300 的地方 只有 3 和 100 的倍數

也就是 2個0已經出現 0 對應的1 之前 第乙個 1 之後的資料 就可以整除 300 記錄餘數 每次遇到便加上

#include

using namespace std;

const

int maxn =

1e5+10;

int sum[maxn]

, cnt[5]

;char str[maxn]

;int

main()

for(

int i =

1; i <= len; i ++

) cout << ans << endl;

return0;

}

2019牛客多校第四場 D triples I

對於二進位制每一位上的1進行考慮,2 0 3 1 2 1 3 2 2 2 3 1 2 3 3 2 那麼我們可以想到把a轉化為二進位制,然後他 3 1的位數有cnt1個,3 2的位數有cnt2個。我們可以想到每個數字最多由2個數字組成,下面給出證明。那麼 sum a 3,如果sum 0,那麼直接乙個數...

2019牛客多校第四場 A meeting

考場上寫了一大坨樹形dp,寫的時候就感覺我這不是跟求樹的最長鏈寫的一毛一樣 然後考後看題解,果然是k個ren所連成的子樹的最長鏈的一半 可以利用反證法證明,如果在長度為d的最長鏈的中間放乙個中心,如果有另外乙個點到這個點的長度 d 1 2,那麼這個點到對面的那個點的長度大於d,所以不存在這樣乙個點。...

2019牛客多校第四場A K

a.給你一張n個點n 1條邊的圖,和k個關鍵點。求乙個點到所有關鍵點距離最大值的最小為多少。乍一看像是對答案二分,但是考慮兩個相距最遠的關鍵點,假設他們的距離為d,那麼答案肯定為 d 1 2 如果有一點到中心點的距離超過了 d 1 2 那麼這個點會成為最遠關鍵點對中的乙個。矛盾。所以題目就變成了如何...