zoukankan      html  css  js  c++  java
  • Codeforces Round #591

    Contest Info


    [Practice Link](https://codeforces.com/contest/1240)
    Solved A B C D E F
    4/6 O O O O - -
    • O 在比赛中通过
    • Ø 赛后通过
    • ! 尝试了但是失败了
    • - 没有尝试

    Solutions


    A. Save the Nature

    题意:
    (n)个数(p_i)

    • 如果一个下标它是(a)的倍数,那么这个位置的价值就是(a_i cdot x\%)
    • 如果一个下标它是(b)的倍数,那么这个位置的价值就是(a_i cdot y\%)
    • 如果一个下标它是(lcm(a, b))的倍数,那么这个位置的价值就是(a_i cdot (x + y)\%)

    现在可以给(p_i)重新排序,问排序最最少多少个前(y)个数,使得前(y)个数的价值和大于等于(k)

    思路:
    二分答案,然后将大的贪心放在大的位置上。

    代码:

    view code
    #include <bits/stdc++.h>
    #define debug(...) { printf("#  "); printf(__VA_ARGS__); puts(""); }
    #define fi first
    #define se second
    #define endl "
    " 
    using namespace std;
    using db = double;
    using ll = long long;
    using ull = unsigned long long; 
    using pII = pair <int, int>;
    using pLL = pair <ll, ll>;
    constexpr int mod = 1e9 + 7;
    template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
    template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
    template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
    inline int rd() { int x; cin >> x; return x; }
    template <class T> inline void rd(T &x) { cin >> x; }
    template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
    inline void pt() { cout << endl; }
    template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
    template <class T> inline void pt(const T &s) { cout << s << "
    "; }
    template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; } 
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
    constexpr int N = 2e5 + 10;
    int n, p[N], x, y, a, b; ll k; 
    bool check(ll mid) {
    	ll lcm = 1ll * a * b / gcd(a, b);
    	ll cnt[3] = {mid / a - mid / lcm, mid / b - mid / lcm, mid / lcm};
    	ll tot = 0;
    	for (int i = 1; i <= mid; ++i) {
    		if (cnt[2]) {
    			tot += 1ll * p[i] / 100 * (x + y);
    			--cnt[2];
    		} else if (cnt[1]) {
    			tot += 1ll * p[i] / 100 * y;
    			--cnt[1];
    		} else if (cnt[0]) {
    			tot += 1ll * p[i] / 100 * x;
    			--cnt[0];
    		} else break;
    	}
    	return tot >= k;
    }
    void run() {
    	cin >> n;
    	for (int i = 1; i <= n; ++i) cin >> p[i];
    	sort(p + 1, p + 1 + n, [&](int x, int y) { return x > y; }); 
    	cin >> x >> a >> y >> b >> k;
    	if (x > y) swap(x, y), swap(a, b);
    	int l = 1, r = n, res = -1;
    	while (r - l >= 0) {
    		int mid = (l + r) >> 1;
    		if (check(mid)) {
    			res = mid;
    			r = mid - 1;
    		} else 
    			l = mid + 1;
    	}
    	pt(res);
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	cout << fixed << setprecision(20);
    	int _T; cin >> _T;
    	while (_T--) run();
    	return 0;
    }
    

    B. Sequence Sorting

    题意:
    给出一个序列(a_i),每次可以选择一种数,将这种数全丢到前面或者全丢到后面。
    问最少操作几次,使得该序列变成非降序。

    思路:
    考虑最多保留多少种数。显然保留下来的肯定是非降序的数,并且是连续的。
    那么直接扫一遍即可。

    代码:

    view code
    #include <bits/stdc++.h>
    #define debug(...) { printf("#  "); printf(__VA_ARGS__); puts(""); }
    #define fi first
    #define se second
    #define endl "
    " 
    using namespace std;
    using db = double;
    using ll = long long;
    using ull = unsigned long long; 
    using pII = pair <int, int>;
    using pLL = pair <ll, ll>;
    constexpr int mod = 1e9 + 7;
    template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
    template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
    template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
    inline int rd() { int x; cin >> x; return x; }
    template <class T> inline void rd(T &x) { cin >> x; }
    template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
    inline void pt() { cout << endl; }
    template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
    template <class T> inline void pt(const T &s) { cout << s << "
    "; }
    template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; } 
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
    constexpr int N = 3e5 + 10;
    int n, a[N], l[N], r[N]; 
    void run() {
    	cin >> n;
    	memset(l, 0x3f, sizeof (l[0]) * (n + 10));
    	memset(r, 0, sizeof (r[0]) * (n + 10));
    	for (int i = 1; i <= n; ++i) {
    		cin >> a[i];
    		chmin(l[a[i]], i);
    		chmax(r[a[i]], i);
    	}
    	int res = 1, tot = 0;
    	int lst = 0, sum = 0; 
    	for (int i = 1; i <= n; ++i) if (r[i] != 0) {
    		++tot;
    		if (l[i] > lst) {
    			lst = r[i];
    			++sum;
    			chmax(res, sum); 
    		} else {
    			lst = r[i]; 
    			sum = 1;
    		}
    	}
    	pt(tot - res);
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	cout << fixed << setprecision(20);
    	int _T; cin >> _T;
    	while (_T--) run();
    	return 0;
    }
    

    C. Paint the Tree

    题意:
    给出一棵树,给每个点涂上(k)种颜色,一种颜色最多涂给两个点,但是有无限种颜色可以涂。
    一条边的价值是如果它两个端点共有至少一种颜色,那么它的价值为它的权值,否则为(0)
    现在问整棵树所有边的价值和最大是多少,在最优涂色方案下。

    思路:
    (f[i][0])表示(i)的子树中并且(i)没有一种颜色可以涂的最大价值,(f[i][1])表示(i)的子树中并且(i)还剩了至少一种颜色可以涂的最大价值。
    那么一个(u),它最多选择(k)(f[v][1] + w)进行转移,我们先假设全都选(f[v][0])转移,然后维护一个堆,里面放的是(f[v][1] + w - f[v][0]),贪心选取前(k)大即可。

    代码:

    view code
    #include <bits/stdc++.h>
    #define debug(...) { printf("#  "); printf(__VA_ARGS__); puts(""); }
    #define fi first
    #define se second
    #define endl "
    " 
    using namespace std;
    using db = double;
    using ll = long long;
    using ull = unsigned long long; 
    using pII = pair <int, int>;
    using pLL = pair <ll, ll>;
    constexpr int mod = 1e9 + 7;
    template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
    template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
    template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
    inline int rd() { int x; cin >> x; return x; }
    template <class T> inline void rd(T &x) { cin >> x; }
    template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
    inline void pt() { cout << endl; }
    template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
    template <class T> inline void pt(const T &s) { cout << s << "
    "; }
    template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; } 
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
    constexpr int N = 5e5 + 10;
    int n, k, fa[N]; ll f[N][2], g[N]; 
    vector <vector<pII>> G;
    void dfs(int u) {
    	f[u][0] = f[u][1] = 0;
    	for (auto &it : G[u]) {
    		int v = it.fi, w = it.se;
    		if (v == fa[u]) continue;
    		fa[v] = u;
    		dfs(v);
    		g[v] = f[v][1] + w - f[v][0];
    		f[u][0] += f[v][0]; 
    		f[u][1] += f[v][0]; 
    	}
    	vector <int> id;
    	for (auto &it : G[u]) if (it.fi != fa[u]) id.push_back(it.fi);
    	sort(id.begin(), id.end(), [&](int x, int y) { return g[x] > g[y]; });
    	for (int i = 0, sze = id.size(); i < k && i < sze; ++i) {
    		int v = id[i];
    		if (g[v] < 0) break;
    		if (i < k - 1) f[u][1] += g[v];
    		f[u][0] += g[v];
    	}
    }
    void run() {
    	cin >> n >> k;
    	G.clear(); G.resize(n + 1); 
    	for (int i = 1, u, v, w; i < n; ++i) {
    		cin >> u >> v >> w;
    		G[u].emplace_back(v, w);
    		G[v].emplace_back(u, w);
    	}
    	fa[1] = 1;
    	dfs(1);
    	pt(max(f[1][0], f[1][1]));
    }
    
    int main() {
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	cout << fixed << setprecision(20);
    	int _T; cin >> _T;
    	while (_T--) run();
    	return 0;
    }
    

    D. Stack Exterminable Arrays

    题意:
    给出(n)个数,维护一个栈,将一个数列加到栈中,这么加:

    • 如果栈空或者栈顶不等于当前数(a_i),那么将(a_i)加入到栈顶
    • 如果栈顶的数等于当前数(a_i),那么栈顶弹出。

    现在询问有多少连续子序列操作完后栈是空的。

    思路:
    我们考虑枚举每个连续子序列的右端点,统计有多少个左端点满足。
    我们用(S[i])表示前(i)个数的操作完后的栈序列。
    那么当且仅当(S[i] = S[j])的时候,([i +1, j])这段序列操作完后栈是空的。
    (S[i])哈希一下即可。

    代码:

    view code
    #include <bits/stdc++.h>
    #define debug(...) { printf("#  "); printf(__VA_ARGS__); puts(""); }
    #define fi first
    #define se second
    #define endl "
    " 
    using namespace std;
    using db = double;
    using ll = long long;
    using ull = unsigned long long; 
    using pII = pair <int, int>;
    using pLL = pair <ll, ll>;
    constexpr int mod = 1e9 + 7;
    template <class T1, class T2> inline void chadd(T1 &x, T2 y) { x += y; while (x >= mod) x -= mod; while (x < 0) x += mod; } 
    template <class T1, class T2> inline void chmax(T1 &x, T2 y) { if (x < y) x = y; }
    template <class T1, class T2> inline void chmin(T1 &x, T2 y) { if (x > y) x = y; }
    inline int rd() { int x; cin >> x; return x; }
    template <class T> inline void rd(T &x) { cin >> x; }
    template <class T> inline void rd(vector <T> &vec) { for (auto &it : vec) cin >> it; }
    inline void pt() { cout << endl; }
    template <class T, class... Ts> void pt(const T& arg, const Ts&... args) { cout << arg << " "; pt(args...); }
    template <class T> inline void pt(const T &s) { cout << s << "
    "; }
    template <class T> inline void pt(const vector <T> &vec) { for (auto &it : vec) cout << it << " "; cout << endl; } 
    ll gcd(ll a, ll b) { return b ? gcd(b, a % b) : a; }
    inline ll qpow(ll base, ll n) { ll res = 1; while (n) { if (n & 1) res = res * base % mod; base = base * base % mod; n >>= 1; } return res; }
    constexpr int N = 3e5 + 10;
    //
    struct Hash {
    	static ull base[N]; 
    	static void init() {
    		base[0] = 1;
    		for (int i = 1; i < N; ++i)
    			base[i] = base[i - 1] * 19260817;  
    	}
    	ull a[N]; 
    	inline void work() { a[0] = 0; }
    	inline void add(int ch, int id) { 
    	    a[id] = a[id - 1] * 19260817 + ch;	
    	}
    }hs;
    ull Hash::base[N] = {0};
    map <ull, int> mp;
    int n, a[N], sta[N]; 
    void run() {
    	cin >> n;
    	for (int i = 1; i <= n; ++i) cin >> a[i];
    	mp.clear();
    	mp[0] = 1; *sta = 0;
    	ll res = 0;
    	hs.work();
    	for (int i = 1; i <= n; ++i) {
    		if (*sta && sta[*sta] == a[i]) --*sta;
    		else sta[++*sta] = a[i], hs.add(a[i], *sta);
    		ull H = hs.a[*sta]; res += mp[H];
    		++mp[H];
    	}
    	pt(res);
    }
    
    int main() {
    	Hash::init();
    	ios::sync_with_stdio(false);
    	cin.tie(nullptr); cout.tie(nullptr);
    	cout << fixed << setprecision(20);
    	int _T; cin >> _T;
    	while (_T--) run();
    	return 0;
    }
    
  • 相关阅读:
    springBoot 2.1.5 pom 文件 unknown 错误
    @HystrixCommand 不能被导包
    SQL数据库连接语句
    ADO.NET中COMMAND对象的ExecuteNonQuery、ExcuteReader和ExecuteScalar方法
    重载和重写的区别
    抽象类和接口的相同点和不同点
    结构详解
    简单工厂和抽象工厂的区别
    DataRead和DataSet的异同
    什么是Web Server
  • 原文地址:https://www.cnblogs.com/Dup4/p/11645863.html
Copyright © 2011-2022 走看看