AtCoder Beginner Contest 107题解

连续两天被新手场教做人。。。

不想缩话。。。

A - Train


Time limit : 2sec / Memory limit : 1024MB

Score : 100 points

Problem Statement

There is an N-car train.

You are given an integer i. Find the value of j such that the following statement is true: "the i-th car from the front of the train is the j-th car from the back."

Constraints

  • 1≤N≤100
  • 1≤iN

Input

Input is given from Standard Input in the following format:

N i

Output

Print the answer.


Sample Input 1

Copy

4 2

Sample Output 1

Copy

3

The second car from the front of a 4-car train is the third car from the back.


Sample Input 2

Copy

1 1

Sample Output 2

Copy

1

Sample Input 3

Copy

15 11

Sample Output 3

Copy

5

额。。。一道考察英语水平的好题,看不懂题我也没有办法QAQ

#include<iostream>
#include<string>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int main()
{
    int a,b;
    cin >> a >> b;
    cout << a-b+1 << endl;
    return 0;
}

B - Grid Compression


Time limit : 2sec / Memory limit : 1024MB

Score : 200 points

Problem Statement

There is a grid of squares with H horizontal rows and W vertical columns. The square at the i-th row from the top and the j-th column from the left is represented as (i,j). Each square is black or white. The color of the square is given as an H-by-W matrix (ai,j). If ai,j is ., the square (i,j) is white; if ai,j is #, the square (i,j) is black.

Snuke is compressing this grid. He will do so by repeatedly performing the following operation while there is a row or column that consists only of white squares:

  • Operation: choose any one row or column that consists only of white squares, remove it and delete the space between the rows or columns.

It can be shown that the final state of the grid is uniquely determined regardless of what row or column is chosen in each operation. Find the final state of the grid.

Constraints

  • 1≤H,W≤100
  • ai,j is . or #.
  • There is at least one black square in the whole grid.

Input

Input is given from Standard Input in the following format:

H W
a1,1…a1,W
:
aH,1…aH,W

Output

Print the final state of the grid in the same format as input (without the numbers of rows and columns); see the samples for clarity.


Sample Input 1

Copy

4 4
##.#
....
##.#
.#.#

Sample Output 1

Copy

###
###
.##

The second row and the third column in the original grid will be removed.


Sample Input 2

Copy

3 3
#..
.#.
..#

Sample Output 2

Copy

#..
.#.
..#

As there is no row or column that consists only of white squares, no operation will be performed.


Sample Input 3

Copy

4 5
.....
.....
..#..
.....

Sample Output 3

Copy

#

Sample Input 4

Copy

7 6
......
....#.
.#....
..#...
..#...
......
.#..#.

Sample Output 4

Copy

..#
#..
.#.
.#.
#.#

每次都会被字符串题小小的卡一下

开两个bool数组记录当前这一行(或列)是否全为‘.’,输出时进行判断

注意这一行啥都没输出时不要换行

好像直接裸做也可以?不管他

#include<iostream>
#include<string>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
string s[110],ans[110];
bool hang[110],lie[110];
int main()
{
    int h,w,i,j;
    cin >> h >> w;
    for (i=0;i<h;i++) cin >> s[i];
    memset(hang,1,sizeof(hang));
    memset(lie,1,sizeof(lie));
    for (i=0;i<h;i++)
    {
        bool all=1;
        for (j=0;j<w;j++)
            if (s[i][j]=='#') {all=0;break;}
        if (all) hang[i]=0;
    }
    for (i=0;i<w;i++)
    {
        bool all=1;
        for (j=0;j<h;j++)
            if (s[j][i]=='#') {all=0;break;}
        if (all) lie[i]=0;
    }

    for (i=0;i<h;i++)
    {
        bool out=0;
        for (j=0;j<w;j++)
            if ((hang[i]) && (lie[j])) {cout << s[i][j];out=1;}
        if (out) cout << endl;
    }
    return 0;
}

 

C - Candles


Time limit : 2sec / Memory limit : 1024MB

Score : 300 points

Problem Statement

There are N candles placed on a number line. The i-th candle from the left is placed on coordinate xi. Here, x1<x2<…<xN holds.

Initially, no candles are burning. Snuke decides to light K of the N candles.

Now, he is at coordinate 0. He can move left and right along the line with speed 1. He can also light a candle when he is at the same position as the candle, in negligible time.

Find the minimum time required to light K candles.

Constraints

  • 1≤N≤105
  • 1≤KN
  • xi is an integer.
  • |xi|≤108
  • x1<x2<…<xN

Input

Input is given from Standard Input in the following format:

N K
x1 x2 … xN

Output

Print the minimum time required to light K candles.


Sample Input 1

Copy

5 3
-30 -10 10 20 50

Sample Output 1

Copy

40

He should move and light candles as follows:

  • Move from coordinate 0 to −10.
  • Light the second candle from the left.
  • Move from coordinate −10 to 10.
  • Light the third candle from the left.
  • Move from coordinate 10 to 20.
  • Light the fourth candle from the left.

Sample Input 2

Copy

3 2
10 20 30

Sample Output 2

Copy

20

Sample Input 3

Copy

1 1
0

Sample Output 3

Copy

0
  • There may be a candle placed at coordinate 0.

Sample Input 4

Copy

8 5
-9 -7 -4 -3 1 2 3 4

Sample Output 4

Copy

10

大意:数轴上有n个点,一个人从0开始走,每次走一个单位长度,要求访问k个点,求他所走的最小距离

题解:首先一个小小的贪心:他所拜访的点必定是一个连续区间(否则你中间就会有空缺,去掉最远的那个点来拜访空缺点一定更优)

所以直接枚举长度为k的区间,当区间首尾同正(负)时,时间加上从0到第一个点。否则加上区间两端的绝对值的最小值(应该很好理解吧)

#include<iostream>
#include<string>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<math.h>
#include<queue>
#include<map>
using namespace std;
int n;
long long a[200500];
int main()
{
    ios::sync_with_stdio(false);
    int k,n,i;
    cin >> n >> k;
    for (i=1;i<=n;i++)
    {
        cin >> a[i];
    }
    long long ans=1e18+7;
    for (i=1;i+k-1<=n;i++)
    {
        long long tmp=a[i+k-1]-a[i];
        if ((a[i]<0) && (a[i+k-1]<0)) tmp+=abs(a[i+k-1]);
        if ((a[i]>0) && (a[i+k-1]>0)) tmp+=a[i];
        if ((a[i]<0) && (a[i+k-1]>0)) tmp+=min(-a[i],a[i+k-1]);
        ans=min(ans,tmp);
    }
    cout << ans;
    return 0;
}

 

D - Median of Medians


Time limit : 2sec / Memory limit : 1024MB

Score : 700 points

Problem Statement

We will define the median of a sequence b of length M, as follows:

  • Let b' be the sequence obtained by sorting b in non-decreasing order. Then, the value of the (M⁄2+1)-th element of b' is the median of b. Here, ⁄ is integer division, rounding down.

For example, the median of (10,30,20) is 20; the median of (10,30,20,40) is 30; the median of (10,10,10,20,30) is 10.

Snuke comes up with the following problem.

You are given a sequence a of length N. For each pair (l,r) (1≤lrN), let ml,r be the median of the contiguous subsequence (al,al+1,…,ar) of a. We will list ml,r for all pairs (l,r) to create a new sequence m. Find the median of m.

Constraints

  • 1≤N≤105
  • ai is an integer.
  • 1≤ai≤109

Input

Input is given from Standard Input in the following format:

N
a1 a2 … aN

Output

Print the median of m.


Sample Input 1

Copy

3
10 30 20

Sample Output 1

Copy

30

The median of each contiguous subsequence of a is as follows:

  • The median of (10) is 10.
  • The median of (30) is 30.
  • The median of (20) is 20.
  • The median of (10,30) is 30.
  • The median of (30,20) is 30.
  • The median of (10,30,20) is 20.

Thus, m=(10,30,20,30,30,20) and the median of m is 30.


Sample Input 2

Copy

1
10

Sample Output 2

Copy

10

Sample Input 3

Copy

10
5 9 5 9 8 9 3 5 4 3

Sample Output 3

Copy

8

大意:定义中位数是一个序列从小到大的第(n/2+1)项(取下整),现给定一个长度为n的序列,对于任意的l,r(1<=l<=r<=n),将这一段数的中位数放入一个新的序列中,求这个新序列的中位数

题解:一看分值A+B+C<D,就有种不详的预感

首先明确,这样的子序列一共只有n(n+1)/2个,因此答案就是在新序列排序后处在n(n+1)/2/2+1的位置上的数

考虑到n很大所以用二分答案

考虑到这里至于数之间的大小关系有关所以离散

那么如何判断我们二分出的答案是否合法呢?

我们回到开头,想要找到出现在这个位置上的数,我们可以统计在新序列中有多少个元素大于等于它就行了

那么怎么处理这个呢?

假设我们当前枚举的数为x,我们还是注意到这里至于数之间的大小关系有关,所以我们可以原序列中比x大或相等的数记为1,比x小的记为-1,得到一个由1与-1组成的序列

此时,l到r之间的中位数大于等于x 也就等价于 得到的新序列(由1与-1组成)中l到r这一段区间中元素和>=0

用前缀和的方式求区间和,可将问题转化成:对于l,r,找到满足Sl-1<=Sr的数对数量

等等,这不就是求逆序对嘛

所以这题就被解决啦QAQ

关于程序多说一句:为了方便求和,程序内的操作可能与上面的题解相反,个人感觉下面的程序更好写一些

注意对负数下标的处理

#include<iostream>
#include<string>
#include<string.h>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<map>
using namespace std;
int a[100100],b[100100],c[200100],n;

int lowbit(int x)
{
    return x&(-x);
}

void add(int x,int val)
{
    x=x+(n+1);
    int i;
    for (i=x;i<=2*n+1;i+=lowbit(i)) c[i]+=val;
}

long long sum(int x)
{
    x+=(n+1);
    int i;
    long long ans=0;
    for (i=x;i>0;i-=lowbit(i)) ans+=c[i];
    return ans;
}

long long work(int num)
{
    int i,tmp=0;long long ans=0;
    for (i=1;i<=n;i++)
    {
        if (a[i]<=num) tmp++; else tmp--;
        ans+=sum(tmp-1);
        add(tmp,1);
    }
    tmp=0;
    for (i=1;i<=n;i++)
    {
        if (a[i]<=num) tmp++; else tmp--;
        add(tmp,-1);
    }
    return ans;
}

int main()
{
    int i;
    scanf("%d",&n);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i];
    }
    memset(c,0,sizeof(c));
    sort(b+1,b+1+n);
    int m=unique(b+1,b+1+n)-b-1;
    int l=1,r=m,ans;
    long long target=(long long)n*(n+1)/2;target=target/2+1;
    add(0,1);
    while (l<=r)
    {
        int mid=(l+r)/2;
        if (work(b[mid])>=target) {ans=b[mid];r=mid-1;}
        else l=mid+1;
    }
    printf("%d\n",ans);
    return 0;
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值