2022 ICPC Gran Premio de Mexico Repechaje 题解

目录

A. Average Walk(签到)

题意:

思路:

代码:

 C. Company Layoffs(签到)

题意:

思路:

代码:

 D. Denji1(模拟/二分)

思路:

代码:

K. Keypad Repetitions(签到,哈希)

题意:

思路:

代码:

L. Ladybug And The Bullet Train(图 / BFS)

题意:

思路:

代码:


A. Average Walk(签到)

John bought a brand new smart watch, this smart watch keeps record of his exercises, mainly, the number of steps John takes during the day. The watch has a feature called "exercise mode", when exercise mode is enabled the watch will "beep" each minute showing the total amount of steps taken since the "exercise mode" was enabled. To take advantage of this feature, John decided to exercise each morning before going to work, his morning exercise will be a walk through a road nearby where he can get fresh air and walk withouth the need to stop to cross streets.

Since John will perform the walk in the mornings, John decided to walk until he has taken at least 3000 steps after a watch "beep", but no more than 15 minutes to avoid having to rush to get to his office in time. John is very consistent with the amount of X steps he takes each minute, this means, John takes exactly X steps each minute, no more, no less.

Given the amount X of stepss John takes each minute, help John find how many minutes he has to walk to finish his morning exercise.

Input

The first and only line of input contains a single integer number X(1≤X≤3000), the number of steps John takes in a minute.

Output

Output a line a single integer number, representing how many minutes John has to walk to finish his morning exercise.

Examples

input

1

output

15

input

300

output

10

input

2999

output

2

input

3000

output

1

题意:

小明每天最多走3000步,一分钟最多走x步,最多走15分钟,问小明能走多少分钟

思路:

3000/x  向上取整,然后和15取较小值即可

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int x;
void solve(){
    cin>>x;
    cout<<min(15,(3000+x-1)/x);
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }

    return 0;
}

 C. Company Layoffs(二分 / 前缀和)

The tech company, Weta, has announced that it will continue to make layoffs once a week for the next M weeks.

For the layoffs, Weta has established that it will fire all employees who have a score greater than Qi. Qi is different every week, and obviously the current week score must be lower than the previous one.

Fortunately, the employees know about this in advance. That is why everyone who would be affected by the week's layoff must make their score equal to Qi.

Weta will not notice this, since Weta does not care about the number of employees fired, but the sum of the employees score.

You, as the representative of the employees, must give Weta the sum of the scores once they have all adjusted their scores to avoid being fired.

Note that only employees with a score greater than Qi can change their score.

Input

The first line of input contains two integer N, M (1 ≤ M < N ≤ 105), the number of employees in Weta and the number of layoffs.

The next line contains N integers Si (1 ≤ Si ≤ 109)

The following M lines describe the layoffs. The i-th of them contains Qi, the score for the layoff of the i−thℎ week. (1 ≤ Qi ≤ 109)

Output

Print M lines with the sum of employees' scores.

Example

input

5 3
2 3 5 5 10
8
7
1

output

23
22
5

题意:

给一个长度为n的数组,在接下来m次查询x,x递减,所有大于x的值都会变成x,然后输出元素和

思路:

先把数组排序,前缀和预处理,然后二分查找第一个大于x的数,直接计算即可

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

void solve(){
    int n,m;
    cin>>n>>m;
    vector<ll>a(n+1);
    vector<ll>pre(n+1);
    
    pre[0]=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
    }
    
    sort(a.begin()+1,a.end());  //排序
    
    for(int i=1;i<=n;i++){
        pre[i]=a[i]+pre[i-1];   //预处理
    }

    while(m--){
        ll x;
        cin>>x;
        ll pos=lower_bound(a.begin()+1,a.end(),x)-a.begin();
        cout<<pre[pos-1]+x*(n-pos+1)<<endl;
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }

    return 0;
}

 D. Denji1(模拟 / 二分)

Denji is trying to kill the algorithm demon. To kill him, Denji must perform this task.

5a03aff0b0416242e074b4baabda99d5.png

Initially, the demon will give Denji an empty array. Then, Denji should perform a sequence of M operations.

An operation can be one of the following:

  1. Add a number to the end of the array.
  2. Delete from the array the number added in operation i.
  3. Add X to the number added in operation i.
  4. Print the number of smaller elements than the number added in operation i.

Unfortunately, Denji only knows how to use chainsaws, not computers, so he asked for your help to kill the algorithm demon.

Input

The first line of input contains an integer M (1 ≤ M ≤ 10^5).

The following m lines describe the operations. The i-th of them begins with a number type (type∈ {1,2,3,4}), which will represent the type of the operation given.

If type = 1, there will be one more integer in the line: A (1 ≤ A ≤ 109), which correspond the operation 1.

If type = 2, there will be one more integer in the line: B(1 ≤B < i), which correspond the operation 2. It is guaranteed that the number added in operation B is still in the array.

If type=3, there will be two integers more in the line: B, A (1 ≤ B < i; 1 ≤ A ≤ 109), which correspond the operation 3. It is guaranteed that the number added in operation B is still in the array.

If type = 4, there will be one more integer in the line: B (1 ≤ B < i), which correspond the operation 4. It is guaranteed that the number added in operation B is still in the array.

It is guaranteed that the first operation is of type 1.

Output

For each operation 4, please print a line containing the answer.

Examples

input

5
1 4
1 5
1 4
4 2
4 3

output

2
0

input

9
1 5
1 5
1 10
4 3
2 2
4 3
3 3 7
4 3
4 1

output

2
1
1
0

思路:

四种操作,维护一个单调容器,模拟操作即可

每次二分找到当前值在容器的位置,进行操作

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll>ans;
ll a[100005];
ll n;
void solve(){
    cin>>n;
    for(int i=1;i<=n;i++){
        ll op,x,y;
        cin>>op;

        if(op==1){    //1为插入
            cin>>x;
            a[i]=x;
            auto pos=lower_bound(ans.begin(),ans.end(),x);
            ans.insert(pos,x);    //找到第一个大于等于x的位置插入
        }

        if(op==2){    //2为删除
            cin>>x;
            auto pos=lower_bound(ans.begin(),ans.end(),a[x]);
            ans.erase(pos);       //找到第一个x的位置删除
        }

        if(op==3){    //3为修改
            cin>>x>>y;    
            auto pos1=lower_bound(ans.begin(),ans.end(),a[x]);
            ans.erase(pos1);    //先把原来的值删去
            a[x]+=y;        //修改
            auto pos2=lower_bound(ans.begin(),ans.end(),a[x]);
            ans.insert(pos2,a[x]);    //修改后添加
        }

        if(op==4){    //4为查询
            cin>>x;
            x=a[x];    //返回在单调容器的下标
            ll anss=lower_bound(ans.begin(),ans.end(),x)-ans.begin();
            cout<<anss<<endl;
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);
    int T=1;
    //cin>>T;
    while(T--){
        solve();
    }

    return 0;
}

K. Keypad Repetitions(签到 / 哈希)

A telephone keypad is a keypad installed on a push-button telephone or similar telecommunication device which usually contains 1010 keys, each of which represents a digit used to dial a telephone number. Today most telephones have an integrated memory, this memory allows users to store common used telephone numbers using a string identifier making it easier for the user to dial numbers without the need of having it memorized or stored in a paper agenda. In order for users to store the string identifier the keypad associates letters to some of the key digits, traditionally this is named as "letter mapping" and the most common one is shown in the following table:

DigitLetters
2abc
3def
4ghi
5jkl
6mno
7pqrs
8tuv
9wxyz

Using this "letter mapping" the user could store the string to identify a telephone number using the keypad, for example, to store the identifier "jhon" the user can press the keypad in the following order: "5466". One problem of this approach is that several identifiers can be represented pressing the keypad in the same order, for example, "5466" that can be used to represent "jhon", can represent also "kino".

Jaime has a list of N identifiers to be stored in his grandfathers old telephone, they suspect a lot of these identifiers can be represented with the same numbers, however, they have not been able to verify their claim, that is why they asked for your help to given the list of identifiers and a set of Q keypad presses to query, find how many identifiers of the list can be represented with each of the keypad presses.

Input

The first line of input contains two integer numbers N (1≤N≤105) and Q (1≤Q≤105), representing the number of identifiers in the list and the number of keypad presses to query. Each of the next N lines contains one of the strings of the list of identifiers, each string consists only of lowercase english alphabet letters and have a length between 1 and 10 characters. Each of the next Q lines contains a keypad press to query, each of the keypad presses contains between 1 and 10 digits between 2 and 9.

Output

For each query in the input print a line with a single integer, representing the number of identifiers in the list that can be represented using the keypad presses in the query.

Example

input

4 5
jhon
abcde
a
kino
5466
2
22233
2222
5466

output

2
1
1
0
2

题意:

模拟手机按键,给n个字符串,询问 按照给定的按键顺序 能按出几个字符串

思路:

把手机按键和字符串用哈希处理,直接读取即可 

代码:

#include<bits/stdc++.h>
using namespace std;
void solve(){
    int n,q;
    cin>>n>>q;
    map<char,char>mm;   //哈希处理手机按键
    for(char ch='a';ch<='c';ch++)mm[ch]='2';
    for(char ch='d';ch<='f';ch++)mm[ch]='3';
    for(char ch='g';ch<='i';ch++)mm[ch]='4';
    for(char ch='j';ch<='l';ch++)mm[ch]='5';
    for(char ch='m';ch<='o';ch++)mm[ch]='6';
    for(char ch='p';ch<='s';ch++)mm[ch]='7';
    for(char ch='t';ch<='v';ch++)mm[ch]='8';
    for(char ch='w';ch<='z';ch++)mm[ch]='9';

    map<string,int>mmm;
    
    for(int i=1;i<=n;i++){
        string s;
        cin>>s;
        for(int j=0;j<s.length();j++)s[j]=mm[s[j]];
        mmm[s]++;       //哈希处理字符串
    }
    
    for(int i=1;i<=q;i++){
        string s;
        cin>>s;
        cout<<mmm[s]<<endl;
    }
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int T=1;
//    cin>>T;
    while(T--){
        solve();
    }

    return 0;
}

L. Ladybug And The Bullet Train(图 / BFS)

Ladybug is an agent specialized in snatch-and-grab jobs, now he has a job that requires him to go to station X and grab a certain suitcase, starting from station 1.

To do that he will be travelling through the stations via a bullet train, so he can move from station A to station B if and only if there exists a train line that connects such stations, it is always possible to reach any station from any other station and that path is unique.

One thing about agent ladybug is that he has very bad luck, he forgot the map of the train lines in the taxi, so, he does not know how to get to station X from his initial station, the lack of a map will not stop him, he will travel through the stations without the map, knowing that eventually he will reach his destination.

Each station has signs that indicate what other stations are reachable taking a train from there. If the agent hasn't already reached station X, he will need to pick an arbitrary station to go to. He will not pick a station he has already visited, except if he reached a dead end (he cannot go to a new station) and return from where he came from.

It's guaranteed that he will at some point reach the station X with this method, but because he has very bad luck, that will end up taking him the longest amount of rides possible. Help his contractor know how many rides the agent has to take to reach station X.

Note:

- A ride is a movement between stations.

- If station Y has a sign that indicates the agent can reach station X taking a train from that station, the agent will take that train first.

Input

The first contains two integers separated by a space N (2≤N≤106) and X (2≤X≤N), indicating the number of stations in train network and the station where the agent should grab the suitcase. Each of the next N−1 lines contains two integer numbers A and B (1≤A,B≤N), indicating that there is a sign at station A which indicates there is a train the agent can use to reach station B from A, and viceversa.

Output

Print one line with an integer number, representing the amount of rides the agent needs to take to reach station X.

Examples

input

5 5
1 2
2 3
3 4
4 5

output

4

input

7 4
2 1
3 1
2 4
2 5
3 6
3 7

output

8

input

2 2
1 2

output

1

题意:

给一棵n个点的无根树,任意两点都联通,求从起点到终点最多可以走多少步

限制条件:(1)除了没有路可走的情况下,不能走已经走过的路(走到死路原路返回)

(2)如果当前位置可以直接到达终点,不会往其他地方走

思路:

BFS搜索,记录终点到起点的距离,搜到挨着终点的第一个点的时候停止这一方向的搜索,其它方向搜到死路为止

除了直接连接起点和终点的路径只走一遍,其它搜到的路都要走两遍(来回) 

代码:

#include<bits/stdc++.h>
using namespace std;
vector<int>edge[1000005];
int dis[1000005];
bool vis[1000005];
void solve(){
    int n,X;
    cin>>n>>X;

    for(int i=1;i<n;i++){
        int u,v;
        cin>>u>>v;
        edge[u].push_back(v);   //建树
        edge[v].push_back(u);
    }

    queue<int>q;
    dis[1]=0;
    vis[1]=1;
    q.push(1);
    long long ans=0;

    while(!q.empty()){      //BFS
        int tmp=q.front();
        q.pop();
        bool flag=1;
        for(auto it:edge[tmp]){     //判断能不能到达终点
            if(it==X){
                flag=0;
                break;
            }
        }

        if(flag==0){    //不往其他地方走
            ans+=2;
            vis[X]=1;
            dis[X]=dis[tmp]+1;
            continue;
        }

        for(auto it:edge[tmp]){     //搜索和他相邻的边
            if(vis[it])continue;
            ans+=2;
            vis[it]=1;
            dis[it]=dis[tmp]+1;
            q.push(it);
        }
    }
    ans-=dis[X];    //减去起点到终点的距离

    cout<<ans<<endl;
}

int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    solve();

    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Auroraaaaaaaaaaaaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值