zoukankan      html  css  js  c++  java
  • Codeforces Round#410 Div.2

    A. Mike and palindrome

    题面

    Mike has a string s consisting of only lowercase English letters. He wants to change exactly one character from the string so that the resulting one is a palindrome.

    A palindrome is a string that reads the same backward as forward, for example strings "z", "aaa", "aba", "abccba" are palindromes, but strings "codeforces", "reality", "ab" are not.

    题意

    只改(不能不改)一个字符,是否能形成回文串,和逆序一起扫一遍,找是不是两个以下不同,如果长度为偶数且完全一样也是不行的。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int ans;
    
    int main() 
    {
    	string d;
    	cin>>d;
    	if (d.size()<=1) return 0*puts("YES");
    	
    	string k2;
    	k2.clear();
    	for (int o=d.size()-1;o>=0;o--) k2.push_back(d[o]);
    	
    	for (int o=0;o<d.size();o++) if (d[o]!=k2[o]) ans++;
    	
    	if (ans==2) return 0*puts("YES");
    	else if (ans==0 && d.size()%2) return 0*puts("YES");
    	else return 0*puts("NO");
    
    }
    

    B. Mike and strings

    题面

    Mike has n strings s1, s2, ..., sn each consisting of lowercase English letters. In one move he can choose a string si, erase the first character and append it to the end of the string. For example, if he has the string "coolmike", in one move he can transform it into the string "oolmikec".

    Now Mike asks himself: what is minimal number of moves that he needs to do in order to make all the strings equal?

    题意

    最少操作几次字符串后,能够让所有字符串一样。比赛的时候太懒了,忘记将所有都弄一遍,导致FST

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    string a[100];
    int f[100];
    int n;
    int ans;
    int outret=0x7fffffff;
    int ret;
    
    int main() 
    {
    	cin>>n;
    	for (int i=1;i<=n;i++) cin>>a[i];
    	a[0]=a[1]+a[1];
    	for (int o=0;o<a[1].size();o++)
    	{
    		a[0]=a[0].substr(1,a[0].size()-1)+a[0][0];
    		ans=0;
    		ret=0;
    		for (int i=1;i<=n;i++) f[i]=a[0].find(a[i]);
    		for (int i=1;i<=n;i++) ans=max(ans,f[i]);
    		for (int i=1;i<=n;i++) if (f[i]<0) return 0*puts("-1");
    		for (int i=1;i<=n;i++) ret+=ans-f[i];
    		outret=min(outret,ret);
    	}
    	
    	cout<<outret;
    	return 0;
    	
    }
    

    官方题解

    dp[i][j]是前i个字符串移动j次变成s[i];

    dp[i][j]=min(dp[i-1][k]+j);

    ans=min(dp[n])

    C. Mike and gcd problem

    题面

    Mike has a sequence A = [a1, a2, ..., an] of length n. He considers the sequence B = [b1, b2, ..., bn] beautiful if the gcd of all its elements is bigger than 1, i.e. .

    Mike wants to change his sequence in order to make it beautiful. In one move he can choose an index i (1 ≤ i < n), delete numbers ai, ai + 1 and put numbers ai - ai + 1, ai + ai + 1 in their place instead, in this order. He wants perform as few operations as possible. Find the minimal number of operations to make sequence A beautiful if it's possible, or tell him that it is impossible to do so.

    is the biggest non-negative number d such that d divides bi for every i (1 ≤ i ≤ n).

    题意

    问操作几次后,他们所有数的gcd变成一样。先考虑本来就一样。然后考虑将所有数字的gcd变成2。

    代码

    #include <bits/stdc++.h>
    using namespace std; 
    
    int gcd(int q,int w)
    {
    	return (q%w==0)?w:gcd(w,q%w);
    }
    
    int n;
    int a[100010];
    
    int main()
    {
        cin>>n;
        cin>>a[1];
        int gm = a[1];
        for (int i = 2; i <= n; i++)
        {
            cin>>a[i];
            gm = gcd(gm, a[i]);
            a[i] %= 2;
        }
        if (gm > 1)
        {
            printf("YES
    0
    ");
            return 0;
        }
        int ans = 0;
        a[1] %= 2;
        a[n + 1] = 10001;
        int i=1;
        while (i <= n)
            if (a[i] == 1)
            {
                if (a[i + 1] == 1)
                {
                    a[i] = a[i + 1] = 0;
                    ans += 1;
                    i += 2;
                }
                else
                {
                    a[i] = 0;
                    ans += 2;
                    i++;
                }
            }
            else i++;
        printf("YES
    %d
    ", ans);
        return 0;
    }
    

    D. Mike and distribution

    题面

    Mike has always been thinking about the harshness of social inequality. He's so obsessed with it that sometimes it even affects him while solving problems. At the moment, Mike has two sequences of positive integers A = [a1, a2, ..., an] and B = [b1, b2, ..., bn] of length n each which he uses to ask people some quite peculiar questions.

    To test you on how good are you at spotting inequality in life, he wants you to find an "unfair" subset of the original sequence. To be more precise, he wants you to select k numbers P = [p1, p2, ..., pk] such that 1 ≤ pi ≤ n for 1 ≤ i ≤ k and elements in P are distinct. Sequence P will represent indices of elements that you'll select from both sequences. He calls such a subset P "unfair" if and only if the following conditions are satisfied: 2·(ap1 + ... + apk) is greater than the sum of all elements from sequence A, and 2·(bp1 + ... + bpk) is greater than the sum of all elements from the sequence B. Also, k should be smaller or equal to because it will be to easy to find sequence P if he allowed you to select too many elements!

    Mike guarantees you that a solution will always exist given the conditions described above, so please help him satisfy his curiosity!

    题意

    取不超过n/2+1个数的子集。使得

    sum(a)<2*sum(sub(a))
    sum(a)<2*sum(sub(a))
    

    成立。当然选择贪心啦=w= 咦 怎么来不及了。。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int n;
    pair<int,int> a[100010];
    int c[100010];
    int ans[100010];
    int cnt;
    
    int cmp(int q,int w)
    {
    	return (a[q].first>a[w].first || (a[q].first==a[w].first && a[q].second>a[w].second));
    }
    
    queue<int> q;
    
    int main()
    {
    	cin>>n;
    	for (int i=1;i<=n;i++) cin>>a[i].first;
    	for (int i=1;i<=n;i++) cin>>a[i].second;
    	for (int i=1;i<=n;i++) c[i]=i;
    	sort(c+1,c+n+1,cmp);
    	
    	int i=1;
    	q.push(c[i++]);
    	while (i<=n)
    	{
    		if (a[c[i]].second>=a[c[i+1]].second) q.push(c[i]);else q.push(c[i+1]); 
    		i+=2;
    	}
    	cnt=q.size();
    	for (int i=0;i<cnt;i++)
    	{
    		ans[i]=q.front();q.pop();
    	}
    	cout<<cnt<<endl;
    	for (int i=0;i<cnt;i++)
    		cout<<ans[i]<<" ";
    
    } 
    

    官方题解

    代码上面已给出,先sort一遍,使得a[c[i]]>=a[c[i+1]],,然后先挑选a[c[1]]。然后后面每两个先选择b[c[i]]大的。

    正确性证明:

    (1) 对于b[pi]每两个当中选大的,则sum(sub(b))*2肯定大于sum(b)。

    (2) 对于a[pi],因为之前选择的a[i]大于后来选择的a[i+]所以sum(sub(a))*2>sum(a).

    E. Mike and code of a permutation

    题面

    time limit per test4 seconds
    memory limit per test512 megabytes
    inputstandard input
    outputstandard output
    Mike has discovered a new way to encode permutations. If he has a permutation P = [p1, p2, ..., pn], he will encode it in the following way:

    Denote by A = [a1, a2, ..., an] a sequence of length n which will represent the code of the permutation. For each i from 1 to n sequentially, he will choose the smallest unmarked j (1 ≤ j ≤ n) such that pi < pj and will assign to ai the number j (in other words he performs ai = j) and will mark j. If there is no such j, he'll assign to ai the number  - 1 (he performs ai =  - 1).

    Mike forgot his original permutation but he remembers its code. Your task is simple: find any permutation such that its code is the same as the code of Mike's original permutation.

    You may assume that there will always be at least one valid permutation.

    题意

    给你一串经过处理的串,让你求原串

    官方题解

    很容易想到拓扑序,那怎么加边呢?(i,a[i])表示i连向a[i]的边,pi<pai。

    如果有[1,a[i]-1]的任意j,且j连向k,a[i]<k<=n,则肯定有pi>pj

    那么我们用一线段树维护区间最大值,来不断找出[1,a[i]-1]中大于a[i]的k,这样保证pi比他们大。

    代码

    #include <bits/stdc++.h>
    using namespace std;
    
    int n;
    int a[500010]; 
    int b[500010];
    int book[500010];
    pair<int,int> tree[500010*4];
    queue<int> q;
    int ans;
    
    void pushup(int k)
    {
    	tree[k]=max(tree[k<<1],tree[k<<1|1]);
    	return;
    } 
    
    void build (int l,int r,int o)
    {
    	if (l==r)
    	{
    		tree[o]=make_pair(b[l],l);
    		return ;
    	}
    	int mid{(l+r)>>1};
    	build (l,mid,o<<1);
    	build (mid+1,r,o<<1|1);
    	pushup(o);
    }
    
    void update(int pos,int val,int l,int r,int o)  
    {  
        if(l==r)
        {  
            tree[o].first=val;  
            return;
        }  
        int mid{(l+r)>>1};  
        if(pos<=mid)  
            update(pos,val,l,mid,o<<1);  
        else  
            update(pos,val,mid+1,r,o<<1|1);  
        pushup(o);  
    }  
    
    pair<int,int> query(int L,int R,int l,int r,int o)  
    {  
        pair<int,int> ret;  
        if (L>R) return make_pair(0,0); 
        if(L<=l&&r<=R) return tree[o];  
        int mid{(l+r)>>1};  
        if(L<=mid)  
            ret=max(ret,query(L,R,l,mid,o<<1));  
        if(R>mid)  
            ret=max(ret,query(L,R,mid+1,r,o<<1|1));  
        return ret;  
    }  
    
    void dfs(int k)
    {
    	book[k]=1;
    	update(k,0,1,n,1);
    	if (b[k]!=n+1 && !book[b[k]]) dfs(b[k]);
    	while (1)
    	{
    		pair<int,int> maxi=query(1,a[k]-1,1,n,1);  
            if(maxi.first>k)  
                dfs(maxi.second);  
            else  
                break;  
    	}
    	q.push(k);
    }
    
    int main() 
    {
    	cin>>n;
    	for (int i=1;i<=n;i++) cin>>a[i]; 
    	for (int i=1;i<=n;i++) b[i]=n+1;
    	for (int i=1;i<=n;i++) 
    		if (a[i]==-1) a[i]=n+1;else b[a[i]]=i;
    	build(1,n,1);
    	for (int i=1;i<=n;i++) if (!book[i]) dfs(i);
    	while (!q.empty())
    	{
    		int x=q.front();q.pop();
    		a[x]=++ans;
    	}
    	for (int i=1;i<=n;i++) cout<<a[i]<<" ";
    }
    

    赛后总结

    在比赛提交错误的次数太多了,导致最后A、C加起来只有888分,而且B FST了,很难受。

    比赛链接:http://codeforces.com/contest/798

  • 相关阅读:
    数据库主键策略
    经历alidns在国外的严重延时
    无题 MVC
    Jquery操作select,左右移动,双击移动 取到所有option的值
    Computop支付网关(一) credit Card
    [转载] 测试的道理
    微信砍价活动总结
    transform,变换
    transition,过渡效果
    文字居底方法
  • 原文地址:https://www.cnblogs.com/EDGsheryl/p/6830138.html
Copyright © 2011-2022 走看看