2019-2020 Saint-Petersburg Open High School Programming Contest 8/11

A

解个方程,就 a = b + c a = b + c a=b+c s − a = s − b = s − c s - a = s - b = s - c sa=sb=sc
s s s是最后做完操作的每个数, a a a是最小的那个数要补多少,然后接这个方程就行。

#include 
#include 
 
int main () {
	int a[3];
	std::cin >> a[0] >> a[1] >> a[2];
	std::sort(a, a + 3);
 
	int s = a[1] + a[2] - a[0];
	int ans = 3 * s - a[0] - a[1] - a[2];
	std::cout << ans / 2 << '\n';
 
	return 0;
}

B

贪心

#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
int const N = 1005;
 
vector<int> g[N], f[N]; ///f add, g minus
int n, m, s;
 
int main() {
	scanf("%d%d%d", &n, &m, &s);
	for (int i = 1; i <= n; ++i) {
		int c, x, y;
		scanf("%d%d%d", &c, &x, &y);
		if (c > 0)
			f[y].push_back(c);
		if (c < 0)
			g[x].push_back(c);
	}
	bool ans = 0;
	for (int i = 1; i <= m; ++i) {
		for (auto p : g[i])
			s += p;
		if (s < 0)
			ans = 1;
		for (auto p : f[i])
			s += p;
	}
	if (ans)
		puts("YES");
	else
		puts("NO");
}

C

分块bitset暴力

#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
const int N = 100000;
const int SMALL = 100;
 
class Set {
    std::unique_ptr<std::vector<int>> v;
    std::unique_ptr<std::bitset<N>> bs;
 
    Set (std::unique_ptr<std::vector<int>> v_, std::unique_ptr<std::bitset<N>> bs_)
        : v(std::move(v_)), bs(std::move(bs_)) {}
 
    void to_bs () {
        bs = std::make_unique<std::bitset<N>>(as_bs());
        if (v) v = nullptr;
    }
 
public:
    Set (): Set(nullptr, nullptr) {}
    Set (std::vector<int> v_): Set(std::make_unique<std::vector<int>>(v_), nullptr) {}
    Set (Set const &rhs): Set() {
        if (rhs.v)
            v = std::make_unique<std::vector<int>>(*rhs.v);
        if (rhs.bs)
            bs = std::make_unique<std::bitset<N>>(*rhs.bs);
    }
 
    Set &operator = (Set &&rhs) {
        v = std::move(rhs.v);
        bs = std::move(rhs.bs);
        return *this;
    }
 
    int count () const {
        if (v) return v->size();
        if (bs) return bs->count();
        return 0;
    }
 
    void clear() {
        v = nullptr;
        bs = nullptr;
    }
 
    std::bitset<N> as_bs () const {
        if (bs)
            return *bs;
        auto ret = std::bitset<N>();
        if (v)
            for (int x: *v)
                ret.set(x);
        return ret;
    }
 
    void set (int x) {
        if (v) {
            if (std::find(v->begin(), v->end(), x) == v->end()) {
                v->push_back(x);
                if (v->size() >= SMALL)
                    to_bs();
            }
        } else if (bs)
            bs->set(x);
        else
            v = std::make_unique<std::vector<int>>(1, x);
    }
 
    void union_ (Set const &rhs) {
        assert(v || bs);
        assert(rhs.v || rhs.bs);
 
        if (v && rhs.v && v->size() + rhs.v->size() < SMALL) {
            for (int x: *rhs.v)
                v->push_back(x);
            std::sort(v->begin(), v->end());
            v->erase(std::unique(v->begin(), v->end()), v->end());
            return;
        }
 
        if (!bs)
            to_bs();
 
        *bs |= rhs.as_bs();
    }
 
    friend std::ostream &operator <<(std::ostream &os, Set const &rhs) {
        os << "{ ";
        if (rhs.v)
            for (int x: *rhs.v)
                os << x << ", ";
        if (rhs.bs)
            for (int i = 0; i < N; ++i)
                if ((*rhs.bs)[i])
                    os << i << ", ";
        return os << "}";
    }
};
 
class UnionSet {
    mutable std::vector<std::pair<int, int>> v;
 
public:
    UnionSet (int n): v(n) {
        for (int i = 0; i < n; ++i)
            v[i] = { i, 1 };
    }
 
    int find(int x) const {
        int f = x;
        while (f != v[f].first)
            f = v[f].first;
        while (x != f) {
            int t = v[x].first;
            v[x].first = f;
            x = t;
        }
        return f;
    }
 
    std::pair<int, int> union_ (int a, int b) {
        a = find(a), b = find(b);
        if (a == b)
            return { -1, -1 };
        if (v[a].second < v[b].second)
            std::swap(a, b);
        v[b].first = a;
        v[a].second += v[b].second;
        return { a, b };
    }
};
 
int main () {
    // freopen("in", "r", stdin);
 
    int n, m, k;
    scanf("%d%d%d", &n, &m, &k);
 
    auto blks = UnionSet(n);
    std::vector<Set> fs, ts;
    for (int i = 0; i < n; ++i){
        fs.push_back(Set { {} });
        ts.push_back(Set { { i } });
    }
 
    for (int i = 0; i < m; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        fs[a].set(b);
        fs[b].set(a);
    }
 
    for (int i = 0; i < k; ++i) {
        int a, b;
        scanf("%d%d", &a, &b);
        --a, --b;
        auto p = blks.union_(a, b);
        if (p.first != -1) {
            ts[p.first].union_(ts[p.second]);
            ts[p.second].clear();
        }
    }
 
    int q;
    scanf("%d", &q);
    for (int i = 0; i < q; ++i) {
        char cmd[2];
        int a, b;
        scanf("%s%d", cmd, &a);
 
        // for (int i = 0; i < n; ++i)
        //     std::cerr << fs[i] << ' ';
        // std::cerr << " <
        // for (int i = 0; i < n; ++i)
        //     std::cerr << ts[i] << ' ';
        // std::cerr << " <
 
        if (cmd[0] == '?') {
            --a;
            int ans = (ts[blks.find(a)].as_bs() & fs[a].as_bs()).count();
            printf("%d\n", ans);
        } else if (cmd[0] == 'T') {
            scanf("%d", &b);
            --a, --b;
            auto p = blks.union_(a, b);
            if (p.first != -1) {
                ts[p.first].union_(ts[p.second]);
                ts[p.second].clear();
            }
        } else {
            scanf("%d", &b);
            --a, --b;
            fs[a].set(b);
            fs[b].set(a);
        }
    }
 
    return 0;
}

D

E

。。。。。

#include 
#include 
 
using namespace std;
 
int random(int l, int r) {
	static std::random_device rd;
	struct timeb timeSeed;
	ftime(&timeSeed);
	size_t seed = timeSeed.time * 1000 + timeSeed.millitm;  // milli time
	static std::mt19937 gen(seed);
	std::uniform_int_distribution<> u(l, r);
	return u(gen);
}
 
int const N = 35;
 
int a[N], x[N];
int n;
long long m = 0;
 
int ans = 0;
void chk(int t, long long s, bool can) {
	if (t >= n) {
		if (can)
			ans += s % m == 0;
		return;
	}
	for (int i = -1; i <= 1; ++i) 
		chk(t + 1, s + x[t] * i, can | (i != 0));
}
 
void rnd() {
	static int lim = (1 << 30) - 1;
	long long sum = 0;
	do {
		sum = 0;
		for (int i = 0; i < n; ++i) {
			x[i] = random(-lim, lim);
			sum += a[i] * x[i];
		}
	} while (sum % m == 0);
}
 
int main() {
	cin >> n;
	for (int i = 0; i < n; ++i)
		cin >> a[i];
 
	int now = 0;
	for (int i = 0; i < n; ++i)
		if (a[i] == 0) 
			x[i] = 1 << (now++);
	for (int i = 0; i < n; ++i)
		if (a[i] == -1)
			x[i] = -(1 <<(now++));
	for (int i = 0; i < n; ++i)
		if (a[i] == 1)
			x[i] = 1 << (now++);
 
	for (int i = 0; i < n; ++i)
		m += x[i] * a[i];
	cout << m << '\n';
	for (int i = 0; i < n; ++i)
		cout << x[i] << ' ';
	cout << '\n';
 
	/*
	ans = 0;
	chk(0, 0, 0);
	cerr <
}

F

为什么最短路题才过了这么点呢(指在我们过题的时候

#include 
#include 
#include 
#include 
#include 
 
const int N = 8;
int64_t dis[N][N];
 
void adde (int a, int b, int64_t w) {
	dis[a][b] = std::min(dis[a][b], w);
	dis[b][a] = std::min(dis[b][a], w);
}
 
int64_t absll (int64_t x) {
	return x >= 0 ? x : -x;
}
 
void init () {
	for (int i = 0; i < N; ++i)
		for (int j = 0; j < N; ++j)
			dis[i][j] = std::numeric_limits<int64_t>::max() / 2;
}
 
int64_t dis2 (int ibeg, int iend) {
	for (int k = 0; k < N; ++k)
		for (int i = 0; i < N; ++i)
			for (int j = 0; j < N; ++j)
				dis[i][j] = std::min(dis[i][j], dis[i][k] + dis[k][j]);
	return dis[ibeg][iend];
}
 
int main () {
	int a, b, c, t[3], d, k, i, l, j;
 
	scanf(
		"%*d%*d%*d"
		"%d%d%d"
		"%d%d%d%d"
		"%d%d%d%d",
		&a, &b, &c,
		&t[0], &t[1], &t[2], &d,
		&k, &i, &l, &j
	);
 
	init();
 
	adde(0, 1, t[0]); // a -- a + 1
	adde(2, 3, t[1]); // b -- b + 1
	adde(4, 5, t[2]); // c -- c + 1
 
	adde(0, 3, d); // a -- b + 1
	adde(2, 5, d); // b -- c + 1
	adde(4, 1, d); // c -- a + 1
 
	int ibeg = 6, iend = 7;
	auto f = [&](int beg, int iline, int x) {
		if (iline == 1) {
			adde(beg, 0, t[0] * absll(a - x));
			adde(beg, 1, t[0] * absll(a + 1 - x));
		} else if (iline == 2) {
			adde(beg, 2, t[1] * absll(b - x));
			adde(beg, 3, t[1] * absll(b + 1 - x));
		} else {
			adde(beg, 4, t[2] * absll(c - x));
			adde(beg, 5, t[2] * absll(c + 1 - x));
		}
	};
	f(ibeg, k, i);
	f(iend, l, j);
	if (k == l)
		adde(ibeg, iend, t[k - 1] * absll(i - j));
 
	auto ans = dis2(ibeg, iend);
	printf("%" PRId64 "\n", ans);
 
	return 0;
}

G

简单暴力简单开桶?x

#include 
#include 
#include 
#include 
 
using namespace std;
 
int const N = 25;
int const M = 40000005;
 
int tot[M];
int f[1 << N];
int a[N];
int n, m;
int dfn[1 << N];
 
void out_(int st) {
	static int ans[N];
	int ret = 0;
	for (int i = 0; i < n; ++i) 
		if ((1 << i) & st)
			ans[++ret] = i;
	cout << ret << '\n';
	for (int i = 1; i <= ret; ++i)
		cout << ans[i] + 1 << ' ';
	cout << '\n';
}
 
void out_ans(int st1, int st2) {
	int uns = st1 & st2;
	st1 -= uns;
	st2 -= uns;
	out_(st1);
	out_(st2);
}
 
int main() {
	cin >> n >> m;
	for (int i = 0; i < n; ++i)
		cin >> a[i];
	for (int i = 0; i < n; ++i)
		dfn[1 << i] = i;
	memset(tot, -1, sizeof(tot));
	tot[0] = 0;
	for (int i = 1, lim = 1 << n; i < lim; ++i) {
		f[i] = (f[i - (i & -i)] + a[dfn[i & -i]]) % m;
		if (tot[f[i]] != -1) {
			out_ans(i, tot[f[i]]);
			return 0;
		}
		tot[f[i]] = i;
	}
	puts("-1");
}

H

简单的暴力简单的卡题意?

#include 
#include 
#include 
#include 
#include 
 
bool check (
	std::string const &ans,
	std::string const &a,
	std::string const &b
) {
	int n = ans.size();
	int cnt[4][2] = {};
	for (int i = 0; i < n; ++i) {
		if (a[i] == ans[i])
			++cnt[0][b[i] == a[i]];
		else
			++cnt[1][b[i] == a[i]];
 
		if (b[i] == ans[i])
			++cnt[2][a[i] == b[i]];
		else
			++cnt[3][a[i] == b[i]];
	}
 
	return
		cnt[0][1] > cnt[0][0] &&
		cnt[1][1] > cnt[1][0] &&
		cnt[2][1] > cnt[2][0] &&
		cnt[3][1] > cnt[3][0];
}
 
int main () {
	int n;
	std::cin >> n;
 
	std::string ans;
	std::cin >> ans;
 
	int m;
	std::cin >> m;
	auto v = std::vector<std::string>(m);
	for (auto &s: v)
		std::cin >> s;
 
	auto ret = std::vector<std::pair<int, int>>();
	for (int i = 0; i < m; ++i)
		for (int j = i + 1; j < m; ++j)
			if (check(ans, v[i], v[j]))
				ret.push_back({ i, j });
 
	std::cout << ret.size() << '\n';
	for (auto &p: ret)
		std::cout << p.first + 1 << ' ' << p.second + 1 << '\n';
 
	return 0;
}

I

其实只要建个图,然后每次相邻三个求交就行x

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
 
using namespace std;
 
int const N = 200005;
 
int a[N][3];
vector<int> G[N];
int ans[N];
map<pair<int, int>, int> mp;
int n;
 
void addedge(int x, int y) {
	G[x].push_back(y);
	// cerr << ">> " << x << ' ' << y << '\n';
}
 
void addedge_solve(int x, int y, int id) {
	if (x > y)
		swap(x, y);
	auto p = make_pair(x, y);
	if (mp[p]) {
		addedge(mp[p], id);
		addedge(id, mp[p]);
	} else
		mp[p] = id;
}
 
int get_nxt(int fa, int id) {
	for (auto c : G[id]) {
		if (c == fa)
			continue;
		return c;
	}
	//assert(false);
	return -1;
}
 
bool in_(int id, int x) {
	for (int i = 0; i < 3; ++i)
		if (x == a[id][i])
			return 1;
	return 0;
}
 
bool chk(int x, int y, int id) {
	if (x != y && in_(id, x) && in_(id, y))
		return 1;
	return 0;
}
 
int find_oth(int id, int x, int y) {
	for (int i = 0; i < 3; ++i) {
		if (a[id][i] == x || a[id][i] == y)
			continue;
		return a[id][i];
	}
	return -1;
}
 
bool dfs(int x, int now, int fa) {
	if (x > n)
		return 1;
	if (x == n) {
		ans[n] = find_oth(now, ans[n - 1], ans[1]);
		if (ans[n] != -1)
			return dfs(x + 1, get_nxt(fa, now), now);
	}
	ans[x] = find_oth(fa, ans[x - 1], ans[x - 2]);
	if (in_(now, ans[x]) == 0)
		return 0;
	return dfs(x + 1, get_nxt(fa, now), now);
}
 
int cross(int x, int y, int z) {
	for (int i = 0; i < 3; ++i)
		for (int j = 0; j < 3; ++j)
			if (a[x][i] == a[y][j])
				for (int k = 0; k < 3; ++k)
					if (a[x][i] == a[z][k])
						return a[x][i];
	return -1;
}
 
int main() {
	mp.clear();
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) 
		for (int j = 0; j < 3; ++j)
			scanf("%d", &a[i][j]);
 
	if (n == 3) {
		puts("1 2 3");
		return 0;
	}
 
	if (n == 4) {
		puts("1 2 3 4");
		return 0;
	}
 
	for (int i = 1; i <= n; ++i) {
		addedge_solve(a[i][0], a[i][1], i);
		addedge_solve(a[i][0], a[i][2], i);
		addedge_solve(a[i][1], a[i][2], i);
	}
	/*
	bool flag = 0;
	for (int k = 0; k < 2; ++k) {
		int nxt = G[1][k];
		int sec = get_nxt(1, nxt);
		for (int i = 0; i < 3; ++i) 
			for (int j = 0; j < 3; ++j) 
				if (flag == 0 && chk(a[1][i], a[nxt][j], nxt)) {
					ans[1] = a[1][i];
					ans[2] = a[nxt][j];
					cerr << "? " << nxt << ' ' << sec << ' ' << ans[1] << ' ' << ans[2] << '\n';
					flag = dfs(3, sec, nxt) &&
							chk(ans[n], ans[2], 1) &&
							chk(ans[1], ans[3], 2);
				}
	}
	*/
	//assert(flag == true);
	int now = 1, nxt = G[1][0];
	for (int i = 1; i <= n; ++i) {
		int sec = get_nxt(now, nxt);
		// cerr << ">> " << now << ' ' << nxt << '\n';
		ans[i] = cross(now, nxt, sec);
		now = nxt;
		nxt = sec;
	}
	for (int i = 1; i <= n; ++i)
		printf("%d%c", ans[i], i == n ? '\n' : ' ');
}

J

K

你可能感兴趣的:(ACM补题)