2020牛客暑期多校訓練營(第八場)

2022-03-01 19:07:16 字數 4463 閱讀 4217

目錄傳送門

solvedab

cdef

ghij

k5 / 11o-

--o-

o-o-

o對時間分治,線段樹維護可撤銷並查集的模板題。

這樣可以直接維護每乙個時刻的連通性,我們只需要求出當前連通塊的個數、雙方孤立的點數即可得出答案。

所以在增、添邊時維護一下點的度數和孤立點數即可。

code

// author : heyuhhh

// created time : 2020/08/04 09:12:36

#include#define mp make_pair

#define fi first

#define se second

#define pb push_back

#define sz(x) (int)(x).size()

#define all(x) (x).begin(), (x).end()

#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

typedef pairpii;

void err(int x)

void err(long long x)

void err(double x)

void err(char x)

void err(const string &x)

void _print()

templatevoid err(const pair&x) ';}

templatevoid err(const t &x) ";}

template void _print(t t, v... v)

#ifdef local

#define dbg(x...) cerr << "[" << #x << "] = ["; _print(x)

#else

#define dbg(x...)

#endif

//head

const int n = 4e5 + 5;

int n, m, q;

int num, cnt, blosz;

int d[n];

struct ufs sta[n];

void init()

}int find(int x)

bool merge(int u, int v) ;

if (h[x] == h[y]) ++h[y];

sz[y] += sz[x];

f[x] = y;

return true;

}void undo(int k)

}int query(int x)

} ufs;

vectornodes[n << 2];

int ans[n];

void add(int o, int l, int r, int l, int r, pii v)

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

if (l <= mid)

if (r > mid)

}void dfs(int o, int l, int r)

if (l == r)

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

dfs(o << 1, l, mid);

dfs(o << 1|1, mid + 1, r);

ufs.undo(cc);

}void run()

}for (int _ = 1; _ <= q; _++) else

}for (auto& it : s)

num = n;

cnt = m;

blosz = n;

dfs(1, 0, q);

for (int i = 1; i <= q; i++)

}int main()

假設我們知道了首項\(x\)以及項數\(m\),那麼我們會發現會對在區間\([(m-2)x+2x+3,(m-2)(x+2)+2x+1]\)即\([mx+3,mx+2m-3]\)的答案嘗試貢獻。

然後觀察有兩點:

接下來就處理第二點。

稍微手模一下就會發現我們可以對區間按照長度對\(4\)取餘進行分類,兩類的貢獻會有不同。

對於模\(4\)為1的區間長度,比如\(1,5,9...\),他們的貢獻類似於\(1,1,2,2,\cdots,2,2,1,1\)這樣對稱的,中間會有個最大值;對於另外一類區間貢獻為\(1,1,2,2,\cdots,t,t,t,\cdots,2,2,1,1\),中間會有三個連續的最大值。

所以根據這個差分一下就行。

**中我用的線段樹維護奇、偶位置的差分,複雜度是兩個log的(列舉\(x,m\)的複雜度是乙個log,是類似於調和級數的,因為是\(m\cdot x\))。

**如下:

code

// author : heyuhhh

// created time : 2020/08/03 13:00:26

#include#define mp make_pair

#define fi first

#define se second

#define pb push_back

#define sz(x) (int)(x).size()

#define all(x) (x).begin(), (x).end()

#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

typedef pairpii;

//head

const int n = 1e5 + 5;

const int n = 100001;

ll ans[n];

struct segment_tree

void update(int o, int l, int r, int l, int r, int v)

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

if(l <= mid) update(o << 1, l, mid, l, r, v);

if(r > mid) update(o << 1|1, mid + 1, r, l, r, v);

}ll res;

void query(int o, int l, int r, int p)

ll query(int p)

}a, b;

void run() else

} else else }}

}for (int i = 1; i < n; i++)

for (int i = 1; i < n; i++)

for (int i = 1; i < n; i++)

int t;

cin >> t;

int _ = 0;

while (t--)

}int main()

直接暴力衝就行。

建圖後對每個連通塊判斷是否存在環即可。

code

// author : heyuhhh

// created time : 2020/08/03 12:14:49

#include#define mp make_pair

#define fi first

#define se second

#define pb push_back

#define sz(x) (int)(x).size()

#define all(x) (x).begin(), (x).end()

#define inf 0x3f3f3f3f

using namespace std;

typedef long long ll;

typedef pairpii;

//head

const int n = 1e5 + 5;

int _;

void run()

if (mp.find(v) == mp.end())

g[mp[u]].push_back(mp[v]);

g[mp[v]].push_back(mp[u]);

++d[mp[u]], ++d[mp[v]];

}vectorvis(tot);

int sum = 0, cnt = 0;

function dfs = [&] (int u) }};

int ans = 0;

for (int i = 0; i < tot; i++) else }}

cout << "case #" << _ << ": ";

cout << ans << '\n';

}int main()

直接貪心,但注意答案可能是\(10^\)會爆long long,然後施展各種奇技淫巧就行。

2020牛客暑期多校訓練營(第八場)

題意 給出n對數,對於每一對,其中如果有沒有選過的數那麼就可以選,就可以選擇那乙個數,ans 需要求最大的ans 思路 隊友很強,思路秒出,十分鐘 一發ac可以把這些數對想成一條邊上的兩個點,可以想像一下如果我要最多的選擇這上面的點,假如這些點構成的邊是一棵樹的話,我們最多在這n個點中能選擇的只有n...

2020牛客暑期多校訓練營(第八場)

總結 這次做的不好,爆零了,雖然確實本場題比較難,但是沒做出來確實問題很大,考慮問題不夠全面仔細。kg 待定給出n對數字a,b。有三種操作。第一種,什麼也不做。第二種,如果ai在在前面沒有被選過,可以選擇ai。第三種,如果bi在前面沒有被選過,可以選擇bi。求最多可以選擇多少種不同的數字。對數字進行...

2020牛客暑期多校訓練營(第八場)

題目鏈結 a all star game 題意 有n個運動員與m個球迷,現給你n個運動員各自的球迷編號,現在問你若要m名球迷都看比賽,至少需要多少名運動員上場?滿足球迷看比賽的條件 1 該球迷喜歡的運動員有上場 2 球迷i與球迷j都有相同的喜歡球員,則球迷j喜歡運動員k,則球迷i也喜歡運動員k 然後...