Codeforces Round #327 (Div. 2)

在大神的指引下,第一次真正意义上“打”了一次cf,虽然惨惨哒,但还是有收获。

A. Wizards' Duel

题中说明碰撞后按相反方向原路返回,虽然两次碰撞,但本质为相遇问题。

Sample test(s)
input
100
50
50
output
50
input
199
60
40
output
119.4
</pre><pre name="code" class="cpp">#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <cmath>
#include <string>
#include <map>
#include<stack>
using namespace std;
int main (void)
{
    float d,p,q;
    cin>>d>>p>>q;
    printf("%.4f",p*d/(p+q));
}
题中最后说明

Namely: let's assume that your answer equals a, and the answer of the jury is b. The checker program will consider your answer correct if 

所以结果至少应保留四位小数(因为没有注意,硬是WA了,又去读了好多遍英文题目,白白浪费时间T^T)


B. Rebranding

给定字符串及需要转换的字符(xi,yi),,将字符串中所有xi变为yi,所有yi变为xi,以此类推,输出最终变化后的字符串。

input
11 6
abacabadaba
a b
b c
a d
e g
f a
b b
output
cdcbcdcfcdc
</pre><pre name="code" class="cpp">#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <cmath>
#include <string>

using namespace std;

char s[200050];
char c[26+5];

int main (void)
{
    std::ios::sync_with_stdio(false);
   
    for(int i=0;i<26;i++)  c[i]=i+'a';
    int num,p;
    char ch1,ch2;
    cin>>num>>p;
    for(int i=0;i<num;i++)
        cin>>s[i];
    for(int i=0;i<p;i++)
    {
        cin>>ch1>>ch2;
        if(ch1!=ch2)
        {
            for(int i=0;i<26;i++)//c中相应元素互换
            {
                if(ch1==c[i])
                    c[i]=ch2;
                else if(ch2==c[i])
                    c[i]=ch1;
            }
        }    
    }
     for(int i=0;i<num;i++)
        cout<<c[s[i]-'a'];
}
之前看题第一反应是用map<char ,vector<int> >,为字符串中每一个字符分配一个不定长数组,储存该字符在字符串中的下标。每次根据该字符所对应下标完成两个字符的交换,交换结束还要进行vector的交换。由于水平有限,写出来交上去一直TLE,改了好多次还是在test11的地方TLE。后来换个角度,从字符本身的变换考虑,通过对最初的保存26个字母的字符数组c进行操作,多次互换确定每个字符所对应的最终新字符,并输出最终字符串。又是水题都做不出系列。。。


C. Median Smoothing

输入一串数字(0或1),通过数组保存,第一项和最后一项不变,求出其余每项与前后两个数字的中位数,并保存在新的数组中,继续对新的数组进行同样操作直到数组不再发生改变,即达到稳定状态。若最终达到稳定状态,输出变换的步骤, 若不能,输出-1。

既然数字串由0和1组成,就只有01相邻才会才发生些改变,即010101..01或者101010...10
0开头:奇:00101011->0010111->000111
偶:001010100->00010100->0001000->0000000

1开头:奇:110101011->111010111->111101111->11111111偶:11010100->11101000->11110000

可以看出,在01相邻构成的子串,若数字个数为奇,则最终稳定的子串与其第一个数字相同,若为偶,则前一半与第一个数字相同,后一半与最后的数字相同。
对于01相邻构成的子串,直接取半,前一半与第一个数字相同,后一半与最后一个数字相同
观察可得步数为(数字子串个数-1)/2,总步数取最大值。

input
4
0 0 1 1
output
0
0 0 1 1
input
5
0 1 0 1 0
output
2
0 0 0 0 0
</pre><pre name="code" class="cpp">#include <cstdio>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstring>
#include <queue>
#include <cmath>
#include <string>
#include <map>
#include<stack>
using namespace std;
int n[500050];
int a[500050];

int main (void)
{
    std::ios::sync_with_stdio(false);
    int num;
    cin>>num;
    int end,begin=0,step=0;
   
    for(int i=0;i<num;i++) cin>>n[i];

    while(begin<num)
    {
        end=num-1;
        a[begin]=n[begin];
        for(int i=begin;i<num-1;i++)
        {
            if(n[i]==n[i+1])
            {
                end=i;
                break;
            }
        }
        step=max((end-begin)/2,step);//获取最大步数
        
        for(int j=0;j<(end-begin)/2+1;j++)
        {
            a[begin+j]=n[begin];
            a[end-j]=n[end];
        }
        begin=end+1;
    }
      cout<<step<<endl;
      cout<<a[0];
      for(int i=1;i<num;i++)
            cout<<" "<<a[i];
    }

最初在while里面加了一个循环语句,以找到01串的始点,结果不幸TLE,优化好久也没想到是这里的问题,其实不用这个循环同样可以获得正确01串,并且总体上减少了时间消耗:)

先写三道。

A long way to go....这次真要努力了!



原文地址:https://www.cnblogs.com/Tuesdayzz/p/5758890.html