zoukankan      html  css  js  c++  java
  • Codeforces Round #658 (Div. 2)

    A.Common Subsequence

    题意

    给你两组数,问你有没有相同 的书,有的话,输出最短的那组(大家都知道,1是最小的)

    AC

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 1005;
    int a[N], x, n, m, flag, t;
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	cin >> t; while (t--) {
    		cin >> n >> m;
    		for (int i = 0; i < n; ++i)cin >> x, a[x]++;
    		flag = 0;
    		for (int i = 0; i < m; ++i) {
    			cin >> x;
    			if (a[x])
    				flag = x;
    		}
    		if (flag) {
    			cout << "YES" << endl;
    			cout << 1 << " " << flag << endl;
    		}
    		else cout << "NO" << endl;
    	}
    }
    

    B.Sequential Nim

    题意:

    两个人玩区石子游戏,有n堆,第i堆有a[i]个,每个人只能按堆的顺序拿,就是前面这堆没有拿完,不能拿下一堆。谁先不能拿就输了。

    思路:

    谁先遇到大于1的石子堆,谁就一定不会输,因为大于1的石子堆,我可以选择全拿完和留一个,这两种状态结果是互斥的,必定会有一个状态的必胜态,所以只要判断到大于1的数前面的1的数量就行,若是全1的情况,那就轮流拿,单独判断一下就行。

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
        int n, t, x, flag, cnt;
        //freopen("in.txt", "r", stdin);
        ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
        cin >> t; while (t--) {
            cin >> n; cnt = 0; flag = 0;
            while (n--) {
                cin >> x;
                if (x == 1 && flag == 0)
                    cnt++;
                if (x > 1)
                    flag = 1;
            }
            if ((cnt % 2 == 1 && flag) || (cnt % 2 == 0 && flag == 0))
                cout << "Second" << endl;
            else
                cout << "First" << endl;
        }
    }
    

    C1Prefix Flip (Easy Version)

    题意;

    给你两个长度相同的01字符串a,b,有一种操作,我们可以把一个字符串长度为x的前缀拿出来,把0,1互换,(就像是异或一下)然后再把这个前缀翻转(掉个头)放回到原字符串中,问我们通过几次这种操作把a转换为b。操作数小于2*n;

    思路:

    因为我们每次拿的都是前缀,那么也就是说,后面的不会动了,那么我们可以从后往前来,遇到不同的,就判断a开头位置和b当前位置(因为不同就要进行”异或“然后翻转,会把第一个数翻转到当前位置上,所以判断a第一个位置和b当前位置)
    如果第一位置和当前位置相同,要把第一位置单独转一下,(因为相同,异或再转过来就不同了)记录一下每次翻转的位置就是答案。

    #include<bits/stdc++.h>
    using namespace std;
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	string a, b; int t; cin >> t;
    	while (t--) {
    		int n; cin >> n;
    		cin >> a >> b; int ans = 0;	
    		for (int i = 0; i < n; ++i)if (a[i] != b[i])ans++;
    		cout << 3 * ans << " ";
    		for (int i = 0; i < n; ++i)if (a[i] != b[i])cout << i + 1 << " 1 " << i + 1 << " ";
    		cout << endl;
    	}
    }
    

    C2题待补

    D. Unmerge(01背包问题,1800)

    题意:

    对于两个数组,定义merge运算:每次把两个数组的首部的较小的那个拿出,并放到一个新的数组中。现在给定一个长度为n*2的排列,问你这个排列是否可能由两个长度为n的数组merge得到?可能则打印yes,否则no。

    思路:

    因为每次拿头部最小的放进新数组,所以一旦我们碰到一个数值a[i],紧跟a[i]后面的并且小于a[i]的全都应该和a[i]是同一组的,那么我们对于每次出现的这种,我们记录它们的长度。如果可能由两个长度为n的组成,那么我们可以找到一些长度,他们加起来等于n,也就是01背包问题了。

    #include<bits/stdc++.h>
    using namespace std;
    const int N = 4e3 + 10;
    int dp[N], d[N], a[N];
    int main() {
    	//freopen("in.txt","r",stdin);
    	ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);
    	int t, n; cin >> t; while (t--) {
    		cin >> n;
    		memset(dp, 0, sizeof dp);
    		for (int i = 1; i <= 2 * n; ++i)cin >> a[i];
    		int mx = a[1], cnt = 1, len = 0;
    		for (int i = 2; i <= 2 * n; ++i) {
    			if (a[i] > mx) {
    				mx = a[i];
    				d[++len] = cnt;
    				cnt = 1;
    			}
    			else
    				cnt++;
    		}
    		d[++len] = cnt;
    		for (int i = 1; i <= len; i++)
    			for (int j = n; j >= d[i]; j--)
    				dp[j] = max(dp[j], dp[j - d[i]] + d[i]);
    		if (dp[n] == n) cout << "YES" << endl;
    		else cout << "NO" << endl;
    	}
    }
    

    E题待补

  • 相关阅读:
    1094. Car Pooling
    121. Best Time to Buy and Sell Stock
    58. Length of Last Word
    510. Inorder Successor in BST II
    198. House Robber
    57. Insert Interval
    15. 3Sum java solutions
    79. Word Search java solutions
    80. Remove Duplicates from Sorted Array II java solutions
    34. Search for a Range java solutions
  • 原文地址:https://www.cnblogs.com/RioTian/p/13372223.html
Copyright © 2011-2022 走看看