首页 > 其他分享 > Codeforces Round 892 (Div. 2)

Codeforces Round 892 (Div. 2)

时间:2023-08-16 23:44:13浏览次数:41  
标签:892 int max Codeforces cin vector 数组 Div dp

Codeforces Round 892 (Div. 2)

目录

A United We Stand

给定长度为\(n\)的数组a,可以将a中元素添加到空数组bc中,满足两个数组均非空,且c中的元素不是b中元素的约数。若不能满足输出-1

c中的元素不是b中元素的约数,即\(b_i \;\% \;c_j \neq 0\)。

可以将a中元素从大到小排序,将所有最大的元素放进c中,其余元素放入b中即满足要求。若b为空,则输出-1

const int N = 110;
int n, a[N];

void solve()
{
    vector<int> b, c;
    cin >> n;
    for(int i = 0; i < n; i ++) cin >> a[i];
    sort(a, a + n, [&](int a, int b){return a > b;});	// 从大到小排序
    for(int i = 0; i < n; i ++)
    {
        if(a[i] == a[0])    c.push_back(a[i]);		// 将所有最大值放入C数组
        else    b.push_back(a[i]);
    }
    if(b.empty())
    {
        cout << "-1\n";
        return ;
    }
    cout << b.size() << " " << c.size() << endl;
    for(auto p : b) cout << p << " ";
    cout << endl;
    for(auto p : c) cout << p << " ";
    cout << endl;
}

B Olya and Game with Arrays

n个数组,最多可以将一个整数从一个数组移动到另一个数组。整数只能从一个数组中移动一次,但整数可以多次添加到一个数组中。对于每个数组找到其中的最小值,然后将这些值相加,求结果的最大值。

要使得最小值尽量大,可以移动每个数组的最小值,那么每个数组对答案的贡献就变成了次小值。将所有最小值插入次小值最小的数组内,可以最小化影响。

取出每个数组的最小值和次小值,将次小值的最小值最小值的最小值取较小值,加上其余所有的次小值。

void solve()
{
    vector<int> minn, lst;
    int n;
    cin >> n;
    for(int i = 0; i < n; i ++)
    {
        int len;
        cin >> len;
        vector<int> a(len);
        for(int i = 0; i < len; i ++) cin >> a[i];
        sort(a.begin(), a.end());
        minn.push_back(a[0]);
        if(len >= 2)    lst.push_back(a[1]);
    }
    sort(minn.begin(), minn.end());
    sort(lst.begin(), lst.end());
    lst[0] = min(lst[0], minn[0]);
    ll ans = 0;
    for(auto p : lst)   ans += p;
    cout << ans << endl;
}

C Another Permutation Problem

成本为\(\Sigma_{i=1}^np_i \cdot i-max_{j=1}^np_j\cdot j\),找出长度\(n\)的所有排列中的最大成本。

先打表找个规律

void solve(int len)
{
    vector<int> a(len), b;
    int ans = 0;
    for(int i = 1; i <= len; i ++)  a[i - 1] = i;
    do{
        int res = 0, tmp = 0;
        for(int i = 0; i < len; i ++)   res += a[i] * (i + 1), tmp = max(tmp, a[i] * (i + 1));
        res -= tmp;
        if(res > ans)    ans = max(ans, res), b = a;
    }while(next_permutation(a.begin(), a.end()));
    cout << ans << endl;
    for(auto p : b) cout << p << " ";
    cout << endl;
}
n ans permutation
2 2 2 1
3 7 1 3 2
4 17 1 2 4 3
5 35 1 2 5 4 3
6 62 1 2 3 6 5 4
7 100 1 2 3 4 7 6 5
8 152 1 2 3 4 8 7 6 5
9 219 1 2 3 4 5 9 8 7 6
10 303 1 2 3 4 5 6 10 9 8 7

通过打表可以发现,后面一部分数翻转时答案最大,排列长度最大为250,可以枚举要翻转的数量

void solve()
{
    ll ans = 0;
    int n;
    cin >> n;
    vector<int> a(n);
    for(int i = 0; i < n; i ++) a[i] = i + 1;
    for(int len = 1; len <= n; len ++)    // 枚举要翻转的长度
    {
        ll res = 0, tmp = 0;
        for(int i = 0; i < n - len; i ++)		// 正序部分
            res += a[i] * (i + 1), tmp = max(tmp, a[i] * (i + 1) * 1ll);	// *1ll转换为ll类型
        for(int i = n - len, j = n; i < n; i ++, j --)	// 逆序部分
            res += a[i] * j, tmp = max(tmp, a[i] * j * 1ll);
        res -= tmp;
        ans = max(ans, res);
    }
    cout << ans << endl;
}

D Andrey and Escape from Capygrad

当处于线段\([l,r]\)上,那么便可以传送到线段\([a,b]\)上,\(l\leq a\leq b\leq r\)。有若干条线段,给定起始位置问最院能传送到哪里

假如当前位置位于\((b,r]\)就没有必要再传送了,所以有效传送区间为\([l,b]\)。

处理出所有的传送区间,进行区间合并,那么在所有的独立区间内都可以任意传送。

二分查找起始位置位于哪个区间左端点的右边,假如起始点在传送区间内就传送到区间的右端点,否则无法传送。

typedef long long ll;
typedef pair<int, int> PII;

vector<PII> vt;

void merge(vector<PII> &segs)	// 区间合并
{
	sort(segs.begin(), segs.end());
	vector<PII> res;
	int st = -2e9, ed = -2e9;
	for(auto seg : segs)
	{
		if(ed < seg.first)
		{
			if(st != -2e9)	res.push_back({st, ed});
			st = seg.first, ed = seg.second;
		}
		else	ed = max(ed, seg.second);
	}
	if(st != -2e9)	res.push_back({st, ed});
	segs = res;
}

bool check(int p, int x)
{
    if(x >= vt[p].first)    return true;
    return false;
}

int bsearch(int x)		// 二分查找位于哪个区间左端点的右边
{
    int l = 0, r = vt.size() - 1;
    while(l < r)
	{
		int mid = l + r + 1 >> 1;
		if(check(mid, x))	l = mid;
		else	r = mid - 1;
	}
	return l;
}

void solve()
{
    vt.clear();
    int n, l, r, a, b, q, x;
    cin >> n;
    for(int i = 0; i < n; i ++)
    {
        cin >> l >> r >> a >> b;
        vt.push_back({l, b});
    }
    merge(vt);
    cin >> q;
    while(q --)
    {
        cin >> x;
        int p = bsearch(x);
        if(x >= vt[p].first && x <= vt[p].second)   x = vt[p].second;	// 若处于传送区间内则传送
        cout << x << " ";
    }
    cout << endl;
}

E Maximum Monogonosity

线段的成本定义为\(|b_l-a_r|+|b_r-a_l|\),求出总长度等于\(k\)且不相交的线段的最大成本总和

显然这是一个DP。参考洛谷题解:CF1859E Maximum Monogonosity - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)

由于\(|a-b|=max(a-b,b-a)\),那么\(|b_l-a_r|+|b_r-a_l|=max(b_l-a_r, a_r-b_l)+max(b_r-a_l,a_l-b_r)\),会出现四种组合方式。

dp[i][j]表示前i个单位中选择长度为j的线段的最大价值。若第i个单位不选,那么由\(dp[i-1][j]\)转移过来。如果选择第i个单位,那么再考虑线段的长度,假设线段的长度为k,那么由dp[i-k][j-k]+cost(i-k+1,i),并从0~j枚举k即可。因此\(O(nk^2)\)的转移方程为

\[dp_{i,j}=max(dp_{i-1,j},max_{k=1}^{j}(dp_{i-k,j-k}+|a_i-b_{i-k+1}|+|b_i-a_{i-k+1}|)) \]

代入绝对值不等式,可以化简为

\[max_{k=1}^{j}dp_{i-k,j-k}+a_i-b_{i-k+1}+b_i-a_{i-k+1} \\ max_{k=1}^{j}dp_{i-k,j-k}+a_i-b_{i-k+1}+a_{i-k+1}-b_i \\ max_{k=1}^{j}dp_{i-k,j-k}+b_{i-k+1}-a_i+b_i-a_{i-k+1} \\ max_{k=1}^{j}dp_{i-k,j-k}+b_{i-k+1}-a_i+a_{i-k+1}-b_i \\ \]

\[(max_{k=1}^{j}dp_{i-k,j-k}-a_{i-k+1}-b_{i-k+1}) +a_i+b_i \\ (max_{k=1}^{j}dp_{i-k,j-k}+a_{i-k+1}-b_{i-k+1}) +a_i-b_i \\ (max_{k=1}^{j}dp_{i-k,j-k}-a_{i-k+1}+b_{i-k+1}) -a_i+b_i \\ (max_{k=1}^{j}dp_{i-k,j-k}+a_{i-k+1}+b_{i-k+1}) -a_i-b_i \\ \]

定义f[x][4]为当前转移到的位置满足\(i-j=x\)时,上面四种情况的最大值分别是多少。复杂度为\(O(nk)\)。

懵懵懂懂看懂了,等我再学一段时间动态规划再来补这个坑。

int n, k;
vector<ll> a(N), b(N);
ll dp[N][N], f[N][4];

void solve()
{
    memset(f, 0x80, sizeof f);	// 这里不是很懂为什么是0x80
    cin >> n >> k;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    for(int i = 1; i <= n; i ++)
    {
        for(int j = 1; j <= k && j <= i; j ++)
        {
            dp[i][j] = dp[i - 1][j];
            f[i - j][0] = max(f[i - j][0], dp[i - 1][j - 1] + a[i] + b[i]);
			f[i - j][1] = max(f[i - j][1], dp[i - 1][j - 1] + a[i] - b[i]);
			f[i - j][2] = max(f[i - j][2], dp[i - 1][j - 1] - a[i] + b[i]);
			f[i - j][3] = max(f[i - j][3], dp[i - 1][j - 1] - a[i] - b[i]);
			dp[i][j] = max(dp[i][j], f[i - j][0] - a[i] - b[i]);
			dp[i][j] = max(dp[i][j], f[i - j][1] + a[i] - b[i]);
			dp[i][j] = max(dp[i][j], f[i - j][2] - a[i] + b[i]);
			dp[i][j] = max(dp[i][j], f[i - j][3] + a[i] + b[i]);
        }
    }
    cout << dp[n][k] << '\n';
}

标签:892,int,max,Codeforces,cin,vector,数组,Div,dp
From: https://www.cnblogs.com/xushengxiang/p/17636503.html

相关文章

  • 2023.08.12 codeforces round 893 div2
    年轻人的第四场div2rank:8217solved:2ratingchange:+31newrating:1354A.Buttons题意:给定a,b,c三种按钮的数量,a按钮只能被Anna按,b按钮只能被Katie按,两个人都可以按c按钮,最后没有按钮可以按的人输,Anna先手,问谁是赢家;两个人肯定优先按c按钮,且Anna是先手,只需比较两人能按的按......
  • Codeforces Round 891 (Div. 3)
    比赛链接:https://codeforces.com/contest/1857A.ArrayColoring题意:一个数列,问能否分成两个和的奇偶性相同的集合思路:因为偶数不改变奇偶性,咱们就统计奇数的个数,能平分成两组就行B.MaximumRounding题意:给一个数,每次可以找一位数不四舍可五入,然后把这个位及后面的数都变成......
  • IE中div被视频遮住的解决方法
    使用embed来内嵌视频,因为视频是windowsmediaplayer,上面想用div浮动一些内容,之前尝试了一些方法,比如1.通过设定不同组件的z-index值2.通过设定wmode值结果都没有效果。最后设定了windowlessVideo=1,终于解决问题。 具体说明一下:“windowlessVideo”属性如为true,则设置成无窗......
  • Educational Codeforces Round 107 (Rated for Div. 2)
    EducationalCodeforcesRound107(RatedforDiv.2)A-ReviewSite思路:数1和3的个数#include<bits/stdc++.h>usingnamespacestd;#defineintlonglong//#defineint__int128#definedoublelongdoubletypedefpair<int,int>PII;typedefpair&l......
  • Codeforces Round 765 (Div. 2) A-E
    A.AncientCivilization好像就是对每个二进制位看一下0多还是1多,选择多的那个数就好了。vp的时候直接猜的,交了一发直接过了voidsolve(){intn=read(),m=read();vector<int>cnt0(m+1),cnt1(m+1);for(inti=1;i<=n;i++){intx=read();for(int......
  • Codeforces Round 893(div2)
    CodeforcesRound893(div2)[A题传送门](Problem-A-Codeforces)A题意:我们有a+b+c个瓶盖,选手1可以拿指定的a个或者c个里面的一个,选手2可以拿指定的b个或者c个里面的一个,可以拿完最后一个的即为获胜者,每个人都有最优策略。A思路:这个题一开始想错了,主要是没有读懂题意,理解清楚......
  • AGC064C Erase and Divide Game
    题面传送门首先考虑你只插入若干个数怎么做:按位从低到高插入一棵Trie,问题就变成:在Trie上每次可以往左儿子走或者往右儿子走,如果当某个人操作的时候为空节点那么这个人就输了。如果我们可以将这棵树建出来那么这个问题就是好解决的,可惜建不出来。仿照从高到低建Trie的方法,将......
  • ABC314 E和CF892 Div2D-E
    ABC314EE-Roulettes(atcoder.jp)大致意思是给你n个轮盘,第i个轮盘等概率的p[i]个点数,玩一次c[i]价钱,问要达到m点的最小期望花费是多少,每次可以任意选一个。乍一看很像背包,偏了方向,所以当时没有做出来。也考虑过其它的DP,关键是0怎么处理没搞明白所以赛后看他人的代码和题解......
  • Codeforces Round 892 (Div. 2)
    CodeforcesRound892(Div.2)A.UnitedWeStand简述题意给定一个长度为$n$的数列$a$,要求将$a$的每个元素分配到数列$b$,$c$中,满足以下两个要求$b,c$不为空,即$l_b\geq1,l_c\geq1$。对于任意$i$和$j$$(1\leqi\leql_b,1\leq......
  • Codeforces Global Round 15
    CodeforcesGlobalRound15A-SubsequencePermutation思路:找出原串与排序后的串不同的个数#include<bits/stdc++.h>usingnamespacestd;voidsolve(){intn;cin>>n;strings;cin>>s;stringt=s;sort(t.begin(),t.end());intans=0;......