Codeforces Round #767 (Div. 2)(A、B、C、D、E)

蒻蒻掉分了,又回到了曾经的灰名,害,只能借鉴大佬的思路照猫画虎了。。。

A. Download More RAM

分析:
直接暴力。由于n的范围比较小,可以直接用while循环判断是否现在还有没有可能增加RAM,若果没有则跳出循环,否则就让K=k+ram.

#include
using namespace std;
int main(){
	int t; cin>>t; 
	while(t--){
		int n,k,a[105],b[105]; cin>>n>>k;
		bool flag=true;
	    vector<int>temp;
		for(int i=1;i<=n;i++) cin>>a[i],temp.push_back(i);
		for(int i=1;i<=n;i++) cin>>b[i];
		while(flag){
			flag =false;
			for(int i=0;i<temp.size();i++){
				int x=temp[i];
				if(a[x]<=k){
					flag=true; k+=b[x];
					temp.erase(temp.begin()+i);
				}
			}
		}
		cout<<k<<endl;
	}
	return 0;
}

B. GCD Arrays

分析:
简单思维题。比赛的时候思路越想越偏,甚至想过直接暴力求出所有数的gcd;当然还好最后也是想到了正确的方法也AC掉了,就是时间有点浪费。
唯一分解定理可知:每一个数都可以拆分为若干个素数的乘积。我们可以在找到序列[l,…,r]之间最频繁的公因子,显然由于序列是连续的,最频繁的公因子就是2。 所以只要求出序列[l…r]中不能整除2的元素个数cnt,再和k作比较即可。显然如果k>=cnt则输出“Yes",否则是”No“。很显然可以发现,不能整除2的元素就是奇数,所以求出奇数个数在做比较即可。 注意:对于l==r的情况要单独处理。

#include
using namespace std;
int main(){
	int t; cin>>t; 
	while(t--){
	    int l,r,k,ji=0,ou=0; cin>>l>>r>>k;
        int len=r-l+1;
        ji=ou=len/2;
        if((len&1)&&(l&1)) ji++;
        else if(len&1) ou++;
		if(l==r&&l>1) cout<<"Yes"<<endl;
		else if(k>=ji) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;

	}
	return 0;
}

接下来就是魔鬼题了,蒻蒻每次div2都是卡死在第3题,一点进步都没有,要放弃了。。。。。
C. Meximum Array

分析:
本题的标记之前我用的是标记数组vis[maxn],但是提交却TLE了;究其原因是每次在初始化数组vis[]的时候使用了memset()函数,导致超时;因此现在的代码里面用的是mapmp作为标记,因为它的初始化很快,只需要mp.clear()蒻蒻由于太菜,只能仿造官方题解的意思解读。
用一个后缀数组mex[i]记录从i-n的MEX值。然后从头开始遍历数组,记录当前位置为pos,若[pos,p]的MEX值==[pos,n]的MEX值,则将结果记录到vector< int >ans中。当然[pos,p]的MEX值需要不断遍历和更新,而[pos,n]的MEX值= =mex[pos]。显然,pos最开始= =1,每次更新pos==p+1。 时间复杂度:O(nlogn)

#include 
#include 
#include 
#include 
#include
#include
using namespace std;
#define INF 0x7fffffff
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn], n, mex[maxn];
map<int, int>mp;
void Init() {
    memset(mex, 0, sizeof(mex));
    mp.clear();
}
int main()
{
    iostream::sync_with_stdio(false);
    int t; cin >> t;
    while (t--) {
        cin >> n;
        Init();
        vector<int>ans;
        int k = 0;
        for (int i = 1; i <= n; i++) cin >> a[i];
        for (int i = n; i >= 1; i--) {
            mp[a[i]] = 1;
            while (mp[k]) k++;
            mex[i] = k;
        }
        mp.clear();
        int res = 0, temp = mex[1];
        for (int p = 1; p <= n;i++) {
                mp[a[p]] = 1;
                while (mp[res]) res++;
                if (res == temp) {
                    ans.push_back(res); 
                    mp.clear();
                    res = 0; temp = mex[p + 1];
                }
        }
        cout << ans.size() << endl;
        for (auto it : ans) cout << it << " ";
        cout << endl;
    }
    return 0;
}

B. Peculiar Movie Preferences

分析:
需要注意的点:子串是顺序拼接的。所以先出现的字符串必须在前面。
由于每个字符串最多三个字符,我们可以分别来分析第i个字符串s(1<=i<=n):
1.s的长度为1:显然此时结果一定是”Yes“,因为一个字符一定是回文串。
2.s的长度为2:此时只需要判断前i-1个字符串中是否出现过s的逆串reverse(s)即可。
3.s的长度为3:此时也有三种情况;(1).之前是否出现过s的逆串reverse(s)。(2)str=s[2]+s[1];前i-1个串中是否出现过长度为2的字符串str。(3).str1=s[1]+s[0];后面n-i个串是否会出现字符串str1。

#include
using namespace std;
const int maxn=1e5+10;
string s;
map<string,int>mp,mpr;
int main(){
	int t;cin>>t;
	while(t--){
		int n;cin>>n;
		mp.clear();  mpr.clear();
		bool flag=false;
		for(int i=1;i<=n;i++) {
			cin>>s;
			if(s.length()==1)	flag=true;
			else{
				mp[s]=1;
				string str=s;
				reverse(str.begin(),str.end());
				if(mp[str]) flag=true;
			    else if(s.length()==2){
				    if(mpr[s]) flag=true;
				} 
			    else if(s.length()==3) {
				string s1,s2;
				s2+=s[2],s2+=s[1];
				s1+=s[1],s1+=s[0];
				mpr[s1]=1;
				if( mp[s2]) flag=true;
				}
			}
	    }
		if(flag) cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	}
	return 0;
}


E. Grid Xor

分析:
本题需要计算所有数的异或结果sum,由于两个相同的数异或结果为0,所以我们只需要保证每一个a[i][j]异或的次数为奇数即可。我们可以从第2行开始遍历每一行,对每一行遍历每一列,由于a[i][j]只会影响a[i-1][j]而不会影响a[i-1][j-1]和a[i-1][j+1];所以每次遍历的时候只需要判断是否a[i-1][j]异或的次数的cnt是否为奇数?若是奇数,则a[i][j]的值不在结果中,否则最终结果sum^=a[i][j],并且(i,j)周围异或的次数加一。如此下去,一直到最后一行,可以保证前i-1行的每一个数异或次数均为奇数。 那么对于最后一行的数异或次数怎么判断呢?蒻蒻也没有想出好办法,但是就是感觉也是奇数。。。。要是有大佬知道,请告诉我趴

#include 
#include 
#include 
#include 
#include
#include
#include
using namespace std;
#define INF 0x7fffffff
typedef long long ll;
const int maxn = 1e3 + 10;
int a[maxn][maxn], cnt[maxn][maxn];
int main()
{
    iostream::sync_with_stdio(false);
    int t; cin >> t;
    while (t--) {
        int n; cin >> n;
        int sum = 0;
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                cin >> a[i][j];
                cnt[i][j] = 0;
            }
        }
        for (int i = 2; i <= n; i++) {
            for (int j = 1; j <= n; j++) {
                if (cnt[i - 1][j] & 1) continue;
                sum ^= a[i][j];
                cnt[i - 1][j]++; cnt[i][j - 1]++; cnt[i][j + 1]++; cnt[i + 1][j] ++;
            }
        }
        cout << sum << endl;
    }
    return 0;
}

你可能感兴趣的:(题目,算法,c++,数据结构)