Codeforces Round #363 (Div. 2) 题解报告

来源:互联网 发布:自媒体是什么 知乎 编辑:程序博客网 时间:2024/05/17 05:18

此文章可以使用目录功能哟↑(点击上方[+])

不知道是不是外国网站的缘故,卡了半个小时之后才进去,好不容易cf早了一次,还被这样玩,难过...

链接→Codeforces Round #363 (Div. 2)

 Problem A. Launch of Collider

Accept: 0    Submit: 0
Time Limit: 2000 MS     Memory Limit : 256 M 

 Problem Description

There will be a launch of a new, powerful and unusual collider very soon, which located along a straight line. n particles will be launched inside it. All of them are located in a straight line and there can not be two or more particles located in the same point. The coordinates of the particles coincide with the distance in meters from the center of the collider, xi is the coordinate of the i-th particle and its position in the collider at the same time. All coordinates of particle positions are even integers.

You know the direction of each particle movement — it will move to the right or to the left after the collider's launch start. All particles begin to move simultaneously at the time of the collider's launch start. Each particle will move straight to the left or straight to the right with the constant speed of 1 meter per microsecond. The collider is big enough so particles can not leave it in the foreseeable time.

Write the program which finds the moment of the first collision of any two particles of the collider. In other words, find the number of microseconds before the first moment when any two particles are at the same point.

 Input

The first line contains the positive integer n (1 ≤ n ≤ 200 000) — the number of particles.

The second line contains n symbols "L" and "R". If the i-th symbol equals "L", then the i-th particle will move to the left, otherwise the i-th symbol equals "R" and the i-th particle will move to the right.

The third line contains the sequence of pairwise distinct even integers x1, x2, ..., xn (0 ≤ xi ≤ 10^9) — the coordinates of particles in the order from the left to the right. It is guaranteed that the coordinates of particles are given in the increasing order.

 Output

In the first line print the only integer — the first moment (in microseconds) when two particles are at the same point and there will be an explosion.

Print the only integer -1, if the collision of particles doesn't happen.

 Sample Input

/*Examples 1*/
4
RLRL
2 4 6 10

/*Examples 2*/
3
LLR
40 50 60

 Sample Output

/*Examples 1*/
1

/*Examples 2*/
-1

Note
In the first sample case the first explosion will
happen in 1 microsecond because the particles number
1 and 2 will simultaneously be at the same point with
the coordinate 3.

In the second sample case there will be no explosion
because there are no particles which will simultaneously
be at the same point.

 Problem Idea

解题思路:

【题意】
其实这道题简单来说就是给你一维坐标上的n个点(坐标及运动方向,各点速度一致),问最早相遇的两点所需的时间。

【类型】
C语言签到题

【分析】
这题,显然,因为每个点的速度一样,所以只有相向而行的两点会相遇,即s[i]=='R'&&s[j]=='L'(j>i)的情况。
而最早相遇的两点,则必定是相邻点,于是j=i+1。
接下来就是暴力每点的方向,凡是前一点为'R',后一点为'L'的状况,都来求一下相遇时间,取最小值。这道题目就做完啦啊。

【时间复杂度&&优化】
O(n)

题目链接→Codeforces 699A

 Source Code

/*Sherlock and Watson and Adler*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<stack>#include<math.h>#include<vector>#include<map>#include<set>#include<cmath>#include<complex>#include<string>#include<algorithm>#include<iostream>#define exp 1e-10#define bitnum(a) __builtin_popcount(a)using namespace std;const int N = 200005;const int M = 1005;const int inf = 1000000007;const int mod = 1000000007;char s[N];int w[N];int main(){    int n,i,Min=inf;    bool flag=false;    scanf("%d",&n);    scanf("%s",s);    for(i=0;i<n;i++)        scanf("%d",&w[i]);    for(i=0;i<n;i++)        if(s[i]=='R')            flag=true;        else        {            if(flag)                Min=min(Min,(w[i]-w[i-1])/2);            flag=false;        }    if(Min!=inf)        printf("%d\n",Min);    else        puts("-1");    return 0;}

 Problem B. One Bomb

Accept: 0    Submit: 0
Time Limit: 1000 MS     Memory Limit : 256 M 

 Problem Description

You are given a description of a depot. It is a rectangular checkered field of n × m size. Each cell in a field can be empty (".") or it can be occupied by a wall ("*").

You have one bomb. If you lay the bomb at the cell (x, y), then after triggering it will wipe out all walls in the row x and all walls in the column y.

You are to determine if it is possible to wipe out all walls in the depot by placing and triggering exactly one bomb. The bomb can be laid both in an empty cell or in a cell occupied by a wall.

 Input

The first line contains two positive integers n and m (1 ≤ n, m ≤ 1000) — the number of rows and columns in the depot field.

The next n lines contain m symbols "." and "*" each — the description of the field. j-th symbol in i-th of them stands for cell (i, j). If the symbol is equal to ".", then the corresponding cell is empty, otherwise it equals "*" and the corresponding cell is occupied by a wall.

 Output

If it is impossible to wipe out all walls by placing and triggering exactly one bomb, then print "NO" in the first line (without quotes).

Otherwise print "YES" (without quotes) in the first line and two integers in the second line — the coordinates of the cell at which the bomb should be laid. If there are multiple answers, print any of them.

 Sample Input

/*Examples 1*/
3 4
.*..
....
.*..

/*Examples 2*/
3 3
..*
.*.
*..

/*Examples 3*/
6 5
..*..
..*..
*****
..*..
..*..
..*..

 Sample Output

/*Examples 1*/
YES
1 2

/*Examples 2*/
NO

/*Examples 3*/
YES
3 3

 Problem Idea

解题思路:

【题意】
给你n*m的矩阵,'.'表示空地,'*'表示墙,若在(x,y)处放置炸弹,可以炸掉第x行,第y列的所有墙。

问只放置一个炸弹能否将矩阵内的所有墙炸毁,若能,输出"YES",以及炸弹放置的位置(矩阵从(1,1)开始,所有多个位置满足,输出任意一个),否则,输出"NO"。

【类型】
暴力

【分析】
这道题其实就是——
所有的墙是不是都在某一行某一列

首先预处理每个墙的位置属于哪一行哪一列,以及墙的总个数

然后暴力枚举矩阵中的每一点(x,y)作为炸弹放置的位置,若第x行第y列的墙个数之和等于墙的总个数,那就说明此点即为所求。

需要注意的一点是若(x,y)点有墙,那上述方法此位置会计算两次,故要去掉一个


【时间复杂度&&优化】
O(nm)

题目链接→Codeforces 699B

 Source Code

/*Sherlock and Watson and Adler*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<stack>#include<math.h>#include<vector>#include<map>#include<set>#include<cmath>#include<complex>#include<string>#include<algorithm>#include<iostream>#define exp 1e-10#define bitnum(a) __builtin_popcount(a)using namespace std;const int N = 1005;const int M = 1005;const int inf = 1000000007;const int mod = 1000000007;char s[N][N];int r[N],c[N];int main(){    int n,m,k1,k2,i,j,k;    k=k1=k2=0;    scanf("%d%d",&n,&m);    for(i=1;i<=n;i++)        scanf("%s",s[i]+1);    for(i=1;i<=n;i++)        for(j=1;j<=m;j++)            if(s[i][j]=='*')                r[i]++,c[j]++,k++;    for(i=1;i<=n;i++)        for(j=1;j<=m;j++)            if(r[i]+c[j]+(s[i][j]=='*'?-1:0)==k)            {                puts("YES");                printf("%d %d\n",i,j);                return 0;            }    puts("NO");    return 0;}

 Problem C. Vacations

Accept: 0    Submit: 0
Time Limit: 1000 MS     Memory Limit : 256 M 

 Problem Description

Vasya has n days of vacations! So he decided to improve his IT skills and do sport. Vasya knows the following information about each of this n days: whether that gym opened and whether a contest was carried out in the Internet on that day. For the i-th day there are four options:

  1. on this day the gym is closed and the contest is not carried out;
  2. on this day the gym is closed and the contest is carried out;
  3. on this day the gym is open and the contest is not carried out;
  4. on this day the gym is open and the contest is carried out.
On each of days Vasya can either have a rest or write the contest (if it is carried out on this day), or do sport (if the gym is open on this day).

Find the minimum number of days on which Vasya will have a rest (it means, he will not do sport and write the contest at the same time). The only limitation that Vasya has —he does not want to do the same activity on two consecutive days: it means, he will not do sport on two consecutive days, and write the contest on two consecutive days.

 Input

The first line contains a positive integer n (1 ≤ n ≤ 100) — the number of days of Vasya's vacations.

The second line contains the sequence of integers a1, a2, ..., an (0 ≤ ai ≤ 3) separated by space, where:

  • ai equals 0, if on the i-th day of vacations the gym is closed and the contest is not carried out;
  • ai equals 1, if on the i-th day of vacations the gym is closed, but the contest is carried out;
  • ai equals 2, if on the i-th day of vacations the gym is open and the contest is not carried out;
  • ai equals 3, if on the i-th day of vacations the gym is open and the contest is carried out.

 Output

Print the minimum possible number of days on which Vasya will have a rest. Remember that Vasya refuses:

  • to do sport on any two consecutive days,
  • to write the contest on any two consecutive days.

 Sample Input

/*Examples 1*/
4
1 3 2 0

/*Examples 2*/
7
1 3 3 2 1 2 3

/*Examples 3*/
2
2 2

 Sample Output

/*Examples 1*/
2

/*Examples 2*/
0

/*Examples 3*/
1

Note
In the first test Vasya can write the contest on the day number 1 and do sport on the day number
3. Thus, he will have a rest for only 2 days.

In the second test Vasya should write contests on days number 1, 3, 5 and 7, in other days do
sport. Thus, he will not have a rest for a single day.

In the third test Vasya can do sport either on a day number 1 or number 2. He can not do sport
in two days, because it will be contrary to the his limitation. Thus, he will have a rest for
only one day.

 Problem Idea

解题思路:

【题意】
有n天时间,Vasya每天只能做一件事(休息,锻炼,做题),且相邻两天不能做一样的事(休息除外),问n天时间至少要休息几天。

此外,每天会给你体育馆的开放情况以及网络上是否有比赛

只有体育馆开放才能锻炼,只有网络赛有比赛才能做题

【类型】
动态规划(dp)

【分析】
显然,此题是一道dp题

故,首先我们要找到转移方程

令dp[i][j]表示第i天做j事所休息的天数(j:0~2 分别表示 休息,做题,锻炼)

相应的,我们可以得到转移方程

        if(s[i]==0)//体育馆未开放,网上也没有比赛            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        else if(s[i]==1)//网上有比赛,体育馆未开放        {            dp[i][1]=min(dp[i-1][1]+1,min(dp[i-1][0],dp[i-1][2]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }        else if(s[i]==2)//体育馆开放,网上没有比赛        {            dp[i][2]=min(dp[i-1][2]+1,min(dp[i-1][0],dp[i-1][1]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }        else//体育馆开放,同时网上也有比赛        {            dp[i][1]=min(dp[i-1][1]+1,min(dp[i-1][0],dp[i-1][2]));            dp[i][2]=min(dp[i-1][2]+1,min(dp[i-1][0],dp[i-1][1]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }
而最终结果则为dp[n][0]~dp[n][2]三者的最小值


【时间复杂度&&优化】
O(n)

题目链接→Codeforce 698A

 Source Code

/*Sherlock and Watson and Adler*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<stack>#include<math.h>#include<vector>#include<map>#include<set>#include<cmath>#include<complex>#include<string>#include<algorithm>#include<iostream>#define exp 1e-10#define bitnum(a) __builtin_popcount(a)using namespace std;const int N = 105;const int M = 1005;const int inf = 1000000007;const int mod = 1000000007;int s[N],dp[N][3];int main(){    int n,i,j;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        scanf("%d",&s[i]);        for(j=0;j<3;j++)            dp[i][j]=inf;    }    for(i=1;i<=n;i++)    {        if(s[i]==0)            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        else if(s[i]==1)        {            dp[i][1]=min(dp[i-1][1]+1,min(dp[i-1][0],dp[i-1][2]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }        else if(s[i]==2)        {            dp[i][2]=min(dp[i-1][2]+1,min(dp[i-1][0],dp[i-1][1]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }        else        {            dp[i][1]=min(dp[i-1][1]+1,min(dp[i-1][0],dp[i-1][2]));            dp[i][2]=min(dp[i-1][2]+1,min(dp[i-1][0],dp[i-1][1]));            dp[i][0]=min(min(dp[i-1][0],dp[i-1][1]),dp[i-1][2])+1;        }    }    printf("%d\n",min(min(dp[n][0],dp[n][1]),dp[n][2]));    return 0;}

 Problem D. Fix a Tree

Accept: 0    Submit: 0
Time Limit: 2000 MS     Memory Limit : 256 M 

 Problem Description

A tree is an undirected connected graph without cycles.

Let's consider a rooted undirected tree with n vertices, numbered 1 through n. There are many ways to represent such a tree. One way is to create an array with n integers p1, p2, ..., pn, where pi denotes a parent of vertex i (here, for convenience a root is considered its own parent).

For this rooted tree the array p is [2, 3, 3, 2].
Given a sequence p1, p2, ..., pn, one is able to restore a tree:

  1. There must be exactly one index r that pr = r. A vertex r is a root of the tree.
  2. For all other n - 1 vertices i, there is an edge between vertex i and vertex pi.
A sequence p1, p2, ..., pn is called valid if the described procedure generates some (any) rooted tree. For example, for n = 3 sequences (1,2,2), (2,3,1) and (2,1,3) are not valid.

You are given a sequence a1, a2, ..., an, not necessarily valid. Your task is to change the minimum number of elements, in order to get a valid sequence. Print the minimum number of changes and an example of a valid sequence after that number of changes. If there are many valid sequences achievable in the minimum number of changes, print any of them.

 Input

The first line of the input contains an integer n (2 ≤ n ≤ 200 000) — the number of vertices in the tree.

The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ n).

 Output

In the first line print the minimum number of elements to change, in order to get a valid sequence.

In the second line, print any valid sequence possible to get from (a1, a2, ..., an) in the minimum number of changes. If there are many such sequences, any of them will be accepted.

 Sample Input

/*Examples 1*/
4
2 3 3 4

/*Examples 2*/
5
3 2 2 5 3

/*Examples 3*/
8
2 3 5 4 1 6 6 7

 Sample Output

/*Examples 1*/
1
2 3 4 4

/*Examples 2*/
0
3 2 2 5 3

/*Examples 3*/
2
2 3 7 8 1 6 6 7

 Problem Idea

解题思路:

【trick&&吐槽】

In the first sample, it's enough to change one element. In the provided output, a sequence represents a tree rooted in a vertex 4 (because p4 = 4), which you can see on the left drawing below. One of other correct solutions would be a sequence 2 3 3 2, representing a tree rooted in vertex 3 (right drawing below). On both drawings, roots are painted red.
In the second sample, the given sequence is already valid.


【题意】
给你一个序列,序列中的第i个数pi是节点i的父亲节点,问至少需要变动几个元素,使得该序列能够构成一棵树,根节点的父亲节点为本身

【类型】
dfs判环

【分析】
显而易见,非法序列的情况有两种:

①出现环,树是无环的,一旦出现环,说明该序列构不成一棵树

②因为题目要求是一棵树,故根节点只有一个,出现多个根节点必定是非法序列

而情况②可以并到①中处理,因为根节点的父亲节点是本身,可以看成是自环

接下来处理就方便了,用dfs判断未处理的节点,是否会构成环,一旦构成环,我们就需要把环拆开,将环中的任意一点指向根节点,若当前无根节点,则指向该点自身,并把此点作为整棵树的根节点,处理一遍就可以了


【时间复杂度&&优化】
O(n)

题目链接→Codeforce 698B

 Source Code

/*Sherlock and Watson and Adler*/#pragma comment(linker, "/STACK:1024000000,1024000000")#include<stdio.h>#include<string.h>#include<stdlib.h>#include<queue>#include<stack>#include<math.h>#include<vector>#include<map>#include<set>#include<cmath>#include<complex>#include<string>#include<algorithm>#include<iostream>#define exp 1e-10#define bitnum(a) __builtin_popcount(a)using namespace std;const int N = 200005;const int M = 1005;const int inf = 1000000007;const int mod = 1000000007;int s[N],k,Max,a[N],v[N];void dfs(int x){    v[x]=1;    if(!v[s[x]])        dfs(s[x]);    else if(v[s[x]]==1)    {        if(k)            s[x]=Max;        else            s[x]=x,k++,Max=x;        v[x]=2;        return;    }    v[x]=2;}int main(){    int n,i,ans=0;    scanf("%d",&n);    for(i=1;i<=n;i++)    {        scanf("%d",&s[i]);        a[i]=s[i];        if(i==s[i])            k++,Max=max(Max,i);    }    for(i=1;i<=n;i++)        if(!v[i])            dfs(i);    for(i=1;i<=n;i++)        if(s[i]!=a[i])            ans++;    printf("%d\n",ans);    for(i=1;i<=n;i++)        printf("%d%c",s[i],i!=n?' ':'\n');    return 0;}

菜鸟成长记

0 0
原创粉丝点击