zoukankan      html  css  js  c++  java
  • Codeforces Round #585 (Div. 2) [补题]

    前言

    2019.9.16

    昨天下午就看了看D题,没有写对,因为要补作业,快点下机了,这周争取把题补完。

    2019.9.17

    这篇文章或者其他文章难免有错别字不被察觉,请读者还是要根据意思来读,不要纠结qwq。

    2019.9.18

    (n<=2*10^5)(O(n))(O(nlogn)) 的算法,知道这招以后就不会乱想方法了。

    A Yellow Cards

    洛谷CF1215A

    开始我还没有想到什么好办法,太丢人了。

    Sooke大佬给出了一个这样的方法:

    • 对于(Min),我们假设先给每个人发((k-1))张牌,(a_1)就是((k_1-1))(a_2)就是((k_2-1)),使每个人达到一种“饱和状态”,剩下每一张黄牌都会使一个人下场。

    • 对于(Max),我们采用暴力枚举(i),在(a_1)(i)张,在(a_2)((n-i))张,找最大值就好了

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    using namespace std;
    inline int read() {
    	int x=0,f=1; char ch=getchar();
    	while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    	while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    	return x * f;
    }
    int n,a1,a2,k1,k2,Max,Min;
    int main()
    {
    	a1 = read(), a2 = read(), k1 = read(), k2 = read(), n = read();
    	Min = max(0, n-((k1-1)*a1+(k2-1)*a2));
    	for(int i=0;i<=n;++i) {
    		Max = max(Max, min(a1 ,i/k1)+min(a2, (n-i)/k2));
    	}
    	printf("%d %d
    ",Min,Max);
    	return 0;
    }
    

    B The Number of Products

    洛谷CF1215B

    想到用动态规划

    (f[i][j][0/1])(i)(j)区间,0表乘积为正数,1表乘积为负数 的子区间数。这个方程十分好推。一想题目没有这么简单,这个方程时间空间复杂度都太大,可能过不了,所以放弃这种状态。

    诶,发现刚才想多了!(同时发现刚才那个方程并不好推,因为子区间是连续的一段)

    下面给出我思考许久的正解

    (f[i][0/1]) 表示以i结尾 0表乘积为正数,1表乘积为负数 的子区间数,那么我们可以推出方程

    • 如果 i 是+,则 (f[i][0]=f[i-1][0]+1)(加上自己),(f[i][1]=f[i-1][1])

    • 如果 i 是-,则 (f[i][0]=f[i-1][1])(f[i][1]=f[i-1][0]+1)

    最后统计答案:

    [ans[0/1]=sum_{i=1}^nf[i][0/1] ]

    总结一下:有区间不能盲目的区间DP,根据题意往往是连续性的采用线性DP。主要还是要看自己的脑子灵不灵活啊!哎~qwq

    Code

    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #define int long long
    using namespace std;
    inline int read() {
    	int x=0,f=1; char ch=getchar();
    	while(ch<'0' || ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    	while(ch>='0'&&ch<='9') { x=(x<<3)+(x<<1)+(ch^48); ch=getchar(); }
    	return x * f;
    }
    const int N = 2e5+7;
    int n,a,l,r;
    int f[N][2];
    signed main()
    {
    	n = read();
    	for(int i=1;i<=n;++i) {
    		a = read();
    		if(a > 0) f[i][0] = f[i-1][0]+1, f[i][1] = f[i-1][1];
    		else f[i][0] = f[i-1][1], f[i][1] = f[i-1][0]+1;
    		l += f[i][0], r += f[i][1];
    	}
    	printf("%lld %lld
    ",r,l);
    	return 0;
    }
    

    D Swap Letters

    洛谷CF1215C

    题解歇礼拜再补吧

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5+7;
    int n,num1,num2;
    int P1[N],P2[N]; 
    char s[N],t[N];
    int main()
    {
    	scanf("%d %s %s",&n,s+1,t+1);
    	int na = 0, nb = 0;
    	for(int i=1;i<=n;++i) {
    		if(s[i]=='a') ++na; else ++nb;
    		if(t[i]=='a') ++na; else ++nb;
    	}
    	if((na&1) || (nb&1)) {
    		puts("-1"); return 0;
    	}
    	for(int i=1;i<=n;++i) {
    		if(s[i]=='a' && t[i]=='b') P1[++num1] = i;
    		if(s[i]=='b' && t[i]=='a') P2[++num2] = i;
    	}
    	if(num1&1) {
    		printf("%d
    ",(num1+num2)/2 + 1);
    		for(int i=1;i<=num1-1;i+=2) printf("%d %d
    ",P1[i], P1[i+1]);
    		for(int i=1;i<=num2-1;i+=2) printf("%d %d
    ",P2[i], P2[i+1]);
    		printf("%d %d
    %d %d
    ",P1[num1], P1[num1], P1[num1], P2[num2]);
    	} else {
    		printf("%d
    ",(num1+num2)/2);
    		for(int i=1;i<=num1;i+=2) printf("%d %d
    ",P1[i], P1[i+1]);
    		for(int i=1;i<=num2;i+=2) printf("%d %d
    ",P2[i], P2[i+1]);
    	}
    	return 0;
    }
    

    D Ticket Game

    洛谷CF1215D

    万万没想到是博弈论,搞得我比赛时还在一边死磕DP

    因为从来没有学过博弈论啊,所以完全没有往这边想。不过看完题解后还是能理解的。

    先设 (ln,ls)是分别左边的问号数 and 数字和,(rn,rs)同理。A是先手,B是后手。B的任务是要 票快乐,A反之。

    先考虑 (ls==rs) 的情况:

    • (ls==rs)(ln==rn) 时,B必赢。自己推一下就知道了,不论A在哪个空填几,B只要在相反方向填上相同数即可。

    • (ls==rs)(ln!=rn) 时,A必赢。一边填完后,会有另一边没有填完,但是这时(填完一边后)会有(ls==rs),所以A随便填几都可以破坏局势。

    再考虑 (ls!=rs) 的情况,先使 (ls > rs),那么:

    • (ls > rs)(ln==rn) 时,A必赢。想一下就知道了。

    • (ls > rs)(ln > rn) 时,A必赢。同理。

    • (ls > rs)(ln<rn) 时,填完左边后,右边相比左边小了(rs-ls),这时设右边空位还有(n)个,那么必须要((n/2)*9==rs-ls) 时 B才能赢,否则就是A赢。想一想就明白了。

    Code

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 2e5+7;
    int n,ln,rn,ls,rs;
    char s[N]; 
    int main()
    {
    	scanf("%d %s",&n,s+1);
    	for(int i=1;i<=n/2;++i) {
    		if(s[i] == '?') ++ln;
    		else ls += s[i]^48;
    	}
    	for(int i=n/2+1;i<=n;++i) {
    		if(s[i] == '?') ++rn;
    		else rs += s[i]^48;
    	}
    	if(ls < rs) swap(ls, rs), swap(ln, rn);
    	if(ls != rs) {
    		if(ln > rn) puts("Monocarp");
    		else {
    			int sum = ls - rs, num = rn - ln;
    			if((num/2)*9 == sum) puts("Bicarp");
    			else puts("Monocarp");
    		}
    	} else {
    		if(ln == rn) puts("Bicarp");
    		else puts("Monocarp");
    	}
    	return 0;
    }
    
  • 相关阅读:
    2018-8-10-win10-uwp-win2d-使用-Path-绘制界面
    2018-8-10-win10-uwp-win2d-使用-Path-绘制界面
    PHP money_format() 函数
    PHP metaphone() 函数
    PHP md5_file() 函数
    PHP md5() 函数
    PHP ltrim() 函数
    查看统计信息
    CF960F Pathwalks_权值线段树_LIS
    hdu 5691 Sitting in line 状压动归
  • 原文地址:https://www.cnblogs.com/BaseAI/p/11529924.html
Copyright © 2011-2022 走看看