codeforce Round #605(Div.3)

  A. Three Friends 

  题目链接

  题目意思:有三个好朋友a,b,c。他们在一个坐标轴上,他们的位置分别是x和xb ,xc,他们三个人都可以往前或者往后走一步,只能走一步。问你他们走了(也可能不走)之后的abs(x -  xb) + abs(xb - xc) + abs(xc - xa )的最小值是多少?

  题目分析:我们可以假定朋友a的坐标最小,朋友b比朋友a更大,但是又比朋友c更小,所以朋友c的位置坐标最大。所以我们可以知道,上面那个式子就是两倍的(最大坐标-最小的坐标),所以我们使得它们的距离最小就可以了。所以怎么使得它们的距离最小呢,那肯定是朋友a向朋友c走一步,朋友c向朋友a走一步,这样就会使得距离最小,真的吗??不不不,肯定不是,如果三个朋友都在相同的位置,a走一步,c走一步,那距离不久变大了,所以我们就可以是ans的初值为0;然后将最大的距离减去最小的距离的值 - 2,得到minn,然后去max(minn,ans),如果minn是负数,那就说明它们肯定可以走到一块,所以距离就是0,如果是正数,那就很遗憾了,它们走不到一块,所以就取那个最小值就可以了。

下面看代码:

 1 #include 
 2 #include 
 3 #include 
 4 
 5 using namespace std;
 6 int num[5];
 7 
 8 int main()
 9 {
10     int t;
11     scanf("%d",&t);
12     while(t--)
13     {
14         for(int i = 1; i <= 3; i++)
15             scanf("%d",&num[i]);
16         sort(num+1,num+4);
17         int ans = 0;
18         ans = max(0,num[3] - num[1] - 2);
19         printf("%d\n",2*ans);
20     }
21     return 0;
22 }
看我

  B. Snow Walking Robot

  题目链接:http://codeforces.com/contest/1272/problem/B

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5  
 6 using namespace std;
 7 const int ma = 1e5 + 10;
 8 char s[ma];
 9 int n,q,num[10];
10 int main()
11 {
12     scanf("%d",&q);
13     int ans,len;
14     int minn1,minn2;
15     while(q--)
16     {
17         scanf(" %s",&s);
18         len = strlen(s);
19         for(int i = 0; i < 4; i++)
20             num[i] = 0;
21         for(int i = 0; i < len; i++)
22         {
23             if(s[i] == 'L')
24                 num[0]++;
25             else if(s[i] == 'R')
26                 num[1]++;
27             else if(s[i] == 'U')
28                 num[2]++;
29             else if(s[i] == 'D')
30                 num[3]++;
31         }
32         minn1 = min(num[0],num[1]);
33         minn2 = min(num[2],num[3]);
34         if(!minn1 && !minn2)
35             printf("0\n\n");
36         else
37         {
38             if(!minn1)
39                 minn2 = 1;
40             if(!minn2)
41                 minn1 = 1;
42             printf("%d\n",2*minn1 + 2*minn2);
43             for(int i = 1; i <= minn1; i++)
44                 printf("%c",'L');
45             for(int i = 1; i <= minn2; i++)
46                 printf("%c",'U');
47             for(int i = 1; i <= minn1 - 1; i++)
48                 printf("%c",'R');
49             for(int i = 1; i <= minn2 - 1; i++)
50                 printf("%c",'D');
51             if(minn1)
52                 printf("%c",'R');
53             if(minn2)
54                 printf("%c",'D');
55             printf("\n");
56         }
57     }
58     return 0;
59 }
View Code

 

  我觉得英语不好的人打cf的比赛很吃亏,题目都看不懂怎么写,要哭了······

  这里要注意这句话:visits no cell other than (0,0) two or more times and ends the path in the cell (0,0).它的意思就是除了(0,0)坐标以外只能visit一次。题目字符串合法的标准是,以坐标(0,0)开始,并且以坐标(0,0)结束,在行走的过程中每个坐标只能走一次,问你将不合法的字符串改为合法的字符串所需要的最小值是多少?,当然也有可能无论怎么改都不合法的,那就输出0;

  题目分析:我们来分情况讨论一下,第一种是只有一个方向的,那肯定不合法的,怎么走也走不回原点:

  第二种:有两个方向。这里又可以分类,一是正反方向,比如左右方向,如果是这样的话,那只能是左右(上下)各走一步;二是竖直方向,比如左上,那肯定也是不合法的。

  第三种:有三个方向,那肯定也不能回到原点。

  第四种:就是有四个方向。因为要回到原点,所以说往左走了多少步,就要往右走多少步,所以要取一个正反的最小值,l = min(num_l,num_r),h = min(num_u,num_d),这样数量上就满足了,然后我们要满足那两个要求了,那我们肯定不能往左走了,然后就往右边走,所以我们可以L,U,R,D这样样,走一个矩形,这样一下子就解决了两个要求。

     代码在上面。

  C. Yet Another Broken Keyboard

  题目链接:http://codeforces.com/contest/1272/problem/C

   c题算是给出了公式,但是要对题意加以理解(我感觉我没理解),根据我所理解的就是还可以用的字母连续的用题目所给的公式n*(n+1)/2,计算字母的个数然后带入公式,将其加起来就可以。这让我明白看不懂的题目猜一下题目意思也行。

  看代码:

 

 1 #include 
 2 #include 
 3 #include 
 4 #include <set>
 5  
 6 using namespace std;
 7 typedef long long ll;
 8 const int ma = 2e5  + 100;
 9 char c[ma];
10 int s[30];
11 int n,k;
12 ll ans;
13  
14 int main()
15 {
16     scanf("%d%d",&n,&k);
17     scanf(" %s",c);
18     getchar();
19     char ss;
20     for(int i = 1; i <= k; i++)
21     {
22         scanf("%c",&ss);
23         getchar();
24         s[ss-'a'] = 1;
25     }
26     ll a;
27     ans = 0;
28     a = 0;
29     for(int i = 0; i < n; i++)
30     {
31         if(s[c[i] - 'a'])
32         {
33             a++;
34             if(i == n-1)
35                 ans += (a+1)*a/2;
36         }
37         else
38             ans += (a+1)*a/2,a = 0;
39     }
40     printf("%lld",ans);
41     return 0;
42 }
View Code

  D. Remove One Element

  这是最有意思的一道题了,dp题,因为本人不太会dp思想,所以我是左思右想还是不会写,然后就看了一下题解,发现题解讲的简单,实现的也简单,我太菜了,要好好学习dp,多写几道题。

  根据题目意思题解是这样定义状态的 Li代表着以位置i开始的最大长度,Ri代表着以i开始的最大增加长度。那怎么实现呢,怎么实现呢。首先这两个数组肯定都有初始值,并且都是1,代表着它们本身,L数组所求的以位置i开始的最大长度所以L要从数组的右边开始,如果num[i] < num[i+1],那么就代表着可以延续下去,所以L[i] = L[i+1] + 1,如果不满足就不延续,遍历一遍数组就可以得到了;那么同样的也可以这样求R数组,但是它要从第二个数开始。然后我们就可以得到这两个数组了,因为题目讲可以将一个数字忽略,所以以i结束的最大长度加上i+2开始的最大长度,历经一边去最大值,如果这样交,你会发现还是过不了,太难过了,怎么老是过不了····,因为少了一种情况就是,数组本身就是递增数组。

  下面是代码:

 

 1 #include 
 2 #include 
 3 #include 
 4  
 5 using namespace std;
 6 const int ma = 2e5 + 10;
 7 int n,l_len[ma],r_len[ma],num[ma];
 8  
 9 int main()
10 {
11     scanf("%d",&n);
12     for(int i = 1;i <= n;i++)
13         scanf("%d",&num[i]);
14     for(int i = 1;i <= n;i++)
15         l_len[i] = r_len[i] = 1;
16     int ans = 1;
17     for(int i = n-1;i >= 1;i--)
18     {
19         if(num[i] < num[i+1])
20             l_len[i] = l_len[i+1] + 1;
21         ans = max(ans,l_len[i]);
22     }
23     for(int i = 2;i <= n;i++)
24     {
25         if(num[i-1] < num[i])
26             r_len[i] = r_len[i-1] + 1;
27         ans = max(ans,r_len[i]);
28     }
29     for(int i = 1;i < n;i++)
30     {
31         if(num[i] < num[i+2])
32             ans = max(ans,r_len[i] + l_len[i+2]);
33     }
34     printf("%d",ans);
35     return 0;
36 }
View Code

 

 

  

你可能感兴趣的:(codeforce Round #605(Div.3))