1. 程式人生 > >2018 計蒜之道 初賽 第一場

2018 計蒜之道 初賽 第一場

得到 ret ++ pair bsp 連通 所有 sizeof -i

百度無人車

二分答案即可。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

int n;
LL a[100010];
LL p, s;
LL ss = 0;
LL l, r;


int main(){

	scanf("%d", &n);
	LL mx = 0;
	rep(i, 1, n) scanf("%lld", a + i), mx = max(mx, a[i]), ss += a[i];

	scanf("%lld%lld", &p, &s);

	LL x = s / p;

	l = 1, r = mx;

	while (l + 1 < r){
		LL mid = (l + r) / 2;
		LL now = 0;
		rep(i, 1, n) now += min(a[i], mid);
		if (ss - now <= x) r = mid;
		else l = mid + 1;
	}

	LL now = 0;
	rep(i, 1, n) now += min(a[i], l);
	if (ss - now <= x) printf("%lld\n", l);
	else printf("%lld\n", r);

	return 0;
}

百度科學家(簡單)

直接模擬

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const int N = 2e2 + 5;

LL a[N];
LL y;
LL ans = 1e18;
bool mp[N][N];
bool v[N];
int n, m, op, x, l, r;
int pos[N], et;


LL calc(int x){
	v[x] = true;
	LL ans = a[x];
	rep(i, 1, et - 1){
		if (!v[i] && mp[x][i]) ans += calc(i);
	}
	return ans;
}

int main(){

	scanf("%d", &n);
	rep(i, 1, n){
		scanf("%lld", &a[i]);
		pos[i] = i;
	}

	et = n + 1;

	scanf("%d", &m);
	while (m--){
		scanf("%d", &op);
		if (op == 0) {
			scanf("%d%lld", &x, &y);
			pos[x] = et;
			a[et++] = y;
		}
		else{
			scanf("%d%d%d", &x, &l, &r);
			rep(j, l, r) mp[pos[x]][pos[j]] = true;
			
		}
	}
	
	rep(i, 1, et - 1){
		memset(v, 0, sizeof v);
		ans = min(ans, calc(i));
	}
	printf("%lld\n", ans);
	return 0;
}

百度科學家(中等)

$∑r-l+1 <= 10^{5}$,根據這個很容易得到這是一個有向圖的模型。

tarjan縮點,找出每個強連通分量的權值和,找到所有出度為0的強連通分量,找一個權值和最小的。

#include <bits/stdc++.h>

using namespace std;

#define rep(i, a, b)	for (int i(a); i <= (b); ++i)
#define dec(i, a, b)	for (int i(a); i >= (b); --i)
#define MP		make_pair
#define fi		first
#define se		second


typedef long long LL;

const int N = 1e5 + 10;

LL a[N], c[N];
LL y;
LL ans = 1e18;

vector <int> mp[N];
stack  <int> stk;
int pos[N];
int low[N], belong[N], dfn[N];
int cnt, ti;
int n, m, op, x, l, r;
int et;
bool vis[N], out[N];


void tarjan(int x, int fa) {
	ti++;
	dfn[x] = low[x] = ti;
	vis[x] = true;
	stk.push(x);

	for (auto y : mp[x]) {
		if (dfn[y] == 0) {
			tarjan(y, x);
			low[x] = min(low[x], low[y]);
		}
		else if (vis[y]) {
			low[x] = min(low[x], dfn[y]);
		}
	}

	if (dfn[x] == low[x]) {
		int y;
		cnt++;

		do{
			y = stk.top(); stk.pop();
			vis[y] = false;
			belong[y] = cnt;
			c[cnt] += a[y];

		}
		while (x != y);
	}
}

void solve(int n){
	memset(dfn, 0, sizeof dfn);
	memset(vis, 0, sizeof vis);
	cnt = ti = 0;
	rep(i, 1, n) if (!dfn[i]) tarjan(i, 0);
}


int main(){

	scanf("%d", &n);
	rep(i, 1, n){
		scanf("%lld", &a[i]);
		pos[i] = i;
	}

	et = n + 1;
	scanf("%d", &m);
	rep(i, 1, m){
		scanf("%d", &op);
		if (op == 0){
			scanf("%d%lld", &x, &y);
			pos[x] = et;
			a[et++] = y;
		}
		else{
			scanf("%d%d%d", &x, &l, &r);
			rep(j, l, r) mp[pos[x]].push_back(pos[j]);
		}
	}

	solve(et - 1);
	memset(out, 0, sizeof out);
	rep(i, 1, et - 1){
		for (auto z : mp[i]){
			if (belong[i] != belong[z]) out[belong[i]] = true;
		}
	}

	rep(i, 1, cnt) if (!out[i]) ans = min(ans, c[i]);
	printf("%lld\n", ans);
	return 0;
}

百度科學家(困難)

留坑。

2018 計蒜之道 初賽 第一場