【Codeforces Contest 1082】 Solution

【Codeforces Contest 1082 Solution】


Problem A Vasya and Book

Time limit per test:2 seconds
Memory limit per test:256 megabytes

Description

Vasya is reading a e-book. The file of the book consists of n n n pages, numbered from 1 1 1 to n n n. The screen is currently displaying the contents of page x x x, and Vasya wants to read the page y y y. There are two buttons on the book which allow Vasya to scroll d d d pages forwards or backwards (but he cannot scroll outside the book). For example, if the book consists of 10 10 10 pages, and d = 3 d=3 d=3, then from the first page Vasya can scroll to the first or to the fourth page by pressing one of the buttons; from the second page — to the first or to the fifth; from the sixth page — to the third or to the ninth; from the eighth — to the fifth or to the tenth.

Help Vasya to calculate the minimum number of times he needs to press a button to move to page y y y.

Input Format

The first line contains one integer t t t ( 1 ≤ t ≤ 1 0 3 ) (1≤t≤10^3) (1t103) — the number of testcases.

Each testcase is denoted by a line containing four integers n n n, x x x, y y y, d d d ( 1 ≤ n , d ≤ 1 0 9 (1≤n,d≤10^9 (1n,d109, 1 ≤ x , y ≤ n ) 1≤x,y≤n) 1x,yn) — the number of pages, the starting page, the desired page, and the number of pages scrolled by pressing one button, respectively.

Output Format

Print one line for each test.

If Vasya can move from page x x x to page y y y, print the minimum number of times he needs to press a button to do it. Otherwise print − 1 −1 1.

Sample Input

  • 3
    10 4 5 2
    5 1 3 4
    20 4 19 3

Sample Output

  • 4
    -1
    5

Hint

In the first test case the optimal sequence is: 4 → 2 → 1 → 3 → 5 4→2→1→3→5 42135.

In the second test case it is possible to get to pages 1 1 1 and 5 5 5.

In the third test case the optimal sequence is: 4 → 7 → 10 → 13 → 16 → 19 4→7→10→13→16→19 4710131619.

Analysis

题目大意

给定一本书的张数,当前位置,目标位置,以及每次翻书能够翻过的张数。求翻到目标位置的最少次数。
特别的,当某次翻动超出了首页或尾页,则翻完后的状态为首页或尾页。

算法分析

第一眼的想法肯定是深搜广搜各种蛇皮搜索。
考虑一下最优情况,肯定从初始位置一路翻下去翻到目标位置。那如果无法达到这种情况呢?是不是也意味着我们怎样左右横跳,都无法到达目标位置?这时候我们只能寻求外力帮助,也就是题目提到的特殊条件,当翻动碰到首尾的时候,就从首尾开始翻动,也就是我们又得到了两种状态。这三种翻动方法可能不互斥,但一定包含所有解。换句话说,如果三种方法都不可行,则无解;三种方法的最优解即为本题最优解。

Code

#include <bits/stdc++.h>
using namespace std;
int main(){
    int T;
    for (cin>>T;T;T--){
        int n,x,y,d;
        cin>>n>>x>>y>>d;
        int a=abs(x-y);
        int b=y-1;
        int c=n-y;
        int ans=1e9+7;
        if (a%d==0) ans=min(ans,a/d);
        if (b%d==0) ans=min(ans,(int) ceil(1.0*(x-1)/d)+b/d);
        if (c%d==0) ans=min(ans,(int) ceil(1.0*(n-x)/d)+c/d);
        cout<<(ans==1e9+7?-1:ans)<<endl;
    }
    return 0;
}

Problem B Vova and Trophies

Time limit per test:2 seconds
Memory limit per test:256 megabytes

Description

Vova has won n n n trophies in different competitions. Each trophy is either golden or silver. The trophies are arranged in a row.

The beauty of the arrangement is the length of the longest subsegment consisting of golden trophies. Vova wants to swap two trophies (not necessarily adjacent ones) to make the arrangement as beautiful as possible — that means, to maximize the length of the longest such subsegment.

Help Vova! Tell hime the maximum possible beauty of the arrangement if he is allowed to do at most one swap.

Input Format

The first line contains one integer n n n ( 2 ≤ n ≤ 1 0 5 ) (2≤n≤10^5) (2n105) — the number of trophies.

The second line contains n n n characters, each of them is either G or S. If the i i i-th character is G, then the i i i-th trophy is a golden one, otherwise it’s silver trophy.

Output Format

Print the maximum possible length of a subsegment of golden trophies, if Vova is allowed to do at most one swap.

Sample Input

  • 10
    GGGSGGGSGG
  • 4
    GGGG
  • 3
    SSS

Sample Output

  • 7
  • 4
  • 0

Analysis

题目大意

给了你一串仅包含G和S的字符串,问交换某两个字符后,串中连续的G最多有几个?

算法分析

我们先把原串中连续相同的字符合并在一起,并记录下这个位置的字符有几个,姑且称之为权值。那么原串就变为了一个带有权值的G、S相间的串。显然,对于仅有一个权值为1的S,如果除了他左右两边的G之外,还有G的话,我们就可以交换掉这个S让两边的G连起来。再考虑权值最大的G,看看是否有多余的G能够与权值最大的G旁边的S交换,使得最大权值再多一。

Code

#include <bits/stdc++.h>
using namespace std;
int b[100007],c[100007],ans,c1,m1,n;
char a[100007];
int main(){
    scanf("%d\n",&n);
    for (int i=1;i<=n;i++) scanf("%c",&a[i]);
    b[0]=b[1]=1; c[1]=a[1]=='G';
    for (int i=2;i<=n;i++){
        if (a[i]==a[i-1]) b[b[0]]++;
        else b[++b[0]]++,c[b[0]]=a[i]=='G';
    }
    for (int i=1;i<=b[0];i++){
        if (c[i]==0 && b[i]==1 && c[i-1]==1 && c[i+1]==1) ans=max(ans,b[i-1]+b[i+1]);
        c1+=c[i];m1=max(m1,(c[i])?b[i]:0);
    }
    if (c1>=2){
        if (ans!=0) printf("%d",max(m1+1,ans+(c1>2)));
        else printf("%d",m1+1);
    }
    else printf("%d",m1);
    return 0;
}

Problem C Multi-Subject Competition

Time limit per test:2 seconds
Memory limit per test:256 megabytes

Description

A multi-subject competition is coming! The competition has m m m different subjects participants can choose from. That’s why Alex (the coach) should form a competition delegation among his students.

He has n candidates. For the i i i-th person he knows subject s i s_i si the candidate specializes in and r i r_i ri — a skill level in his specialization (this level can be negative!).

The rules of the competition require each delegation to choose some subset of subjects they will participate in. The only restriction is that the number of students from the team participating in each of the chosen subjects should be the same.

Alex decided that each candidate would participate only in the subject he specializes in. Now Alex wonders whom he has to choose to maximize the total sum of skill levels of all delegates, or just skip the competition this year if every valid non-empty delegation has negative sum.

(Of course, Alex doesn’t have any spare money so each delegate he chooses must participate in the competition).

Input Format

The first line contains two integers n n n and m m m ( 1 ≤ n ≤ 1 0 5 , 1 ≤ m ≤ 1 0 5 ) (1≤n≤10^5, 1≤m≤10^5) (1n105,1m105) — the number of candidates and the number of subjects.

The next n n n lines contains two integers per line: s i s_i si and r i r_i ri ( 1 ≤ s i ≤ m , − 1 0 4 ≤ r i ≤ 1 0 4 ) (1≤s_i≤m, −10^4≤r_i≤10^4) (1sim,104ri104) — the subject of specialization and the skill level of the i i i-th candidate.

Output Format

Print the single integer — the maximum total sum of skills of delegates who form a valid delegation (according to rules above) or 0 0 0 if every valid non-empty delegation has negative sum.

Sample Input

  • 6 3
    2 6
    3 6
    2 5
    3 5
    1 9
    3 1
  • 5 3
    2 6
    3 6
    2 5
    3 5
    1 11
  • 5 2
    1 -1
    1 -5
    2 -1
    2 -1
    1 -10

Sample Output

  • 22
  • 23
  • 0

Hint

In the first example it’s optimal to choose candidates 1 1 1, 2 2 2, 3 3 3, 4 4 4, so two of them specialize in the 2 2 2-nd subject and other two in the 3 3 3-rd. The total sum is 6 + 6 + 5 + 5 = 22 6+6+5+5=22 6+6+5+5=22.

In the second example it’s optimal to choose candidates 1 1 1, 2 2 2 and 5 5 5. One person in each subject and the total sum is 6 + 6 + 11 = 23 6+6+11=23 6+6+11=23.

In the third example it’s impossible to obtain a non-negative sum.

Analysis

题目大意

给出n个二元组,第一个元素为编号,第二个元素为权值,保证编号在[1,m]内。每个编号要么不取,要么取出相同数量的二元组。询问权值之和的最大值。

算法分析

首先贪心的思路,取出的二元组一定是相同编号中最大的那几个。在此基础上,依次判断取出i个能够得到的最大值,再取最大值即为答案。

注意到数据范围,只能考虑做法O(nlogn)或O(n)的做法。

我的做法是:记二元组为a,将a以编号为第一关键字升序,权值为第二关键字降序,进行排列。然后在编号相同的区间内做前缀和处理。其次,记录下每个区间的首地址(这里记为b),以及每个编号的二元组的个数(这里记为c),对c排列。对于每次要取出的个数i,只需要把c中大于等于i的编号且这种编号中前i个的和大于等于0的值加起来,就是取i个二元组的最大值。枚举i求最大,即为答案。

Code

#include <bits/stdc++.h>
using namespace std;
pair <int,int> a[100007],c[100007];
int b[100007];
int n,m,ans,mm=1;
inline bool cmp(const pair <int,int> a,const pair <int,int> b){
    return a.first==b.first?a.second>b.second:a.first<b.first;
}
int main(){
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;i++) scanf("%d%d",&a[i].first,&a[i].second);
    sort(a+1,a+1+n,cmp);
    b[a[1].first]=1; 
    c[a[1].first].first=1;
    c[a[1].first].second=a[1].first;
    for (int i=2;i<=n;i++){
        if (a[i].first==a[i-1].first) 
            a[i].second+=a[i-1].second,c[a[i].first].first++;
        else b[a[i].first]=i,c[a[i].first].first=1;
        mm=max(c[a[i].first].first,mm); 
        c[a[i].first].second=a[i].first;
    }
    sort(c+1,c+1+m);
    for (int i=1;i<=mm;i++){
        int s=0;
        for (int j=m;j>=1 && c[j].first>=i;j--) 
            s+=a[i-1+b[c[j].second]].second>0?a[i-1+b[c[j].second]].second:0;
        ans=max(ans,s);
    }
    printf("%d",max(ans,0));
}

Problem D

Time limit per test:2 seconds
Memory limit per test:256 megabytes

Description

Graph constructive problems are back! This time the graph you are asked to build should match the following properties.

The graph is connected if and only if there exists a path between every pair of vertices.

The diameter (aka “longest shortest path”) of a connected undirected graph is the maximum number of edges in the shortest path between any pair of its vertices.

The degree of a vertex if the number of edges incident to it.

Given a sequence of n n n integers a 1 , a 2 , . . . , a n a_1,a_2,...,a_n a1,a2,...,an construct a connected undirected graph of n n n vertices such that:

  • the graph contains no self-loops and no multiple edges;
  • the degree d i d_i di of the i i i-th vertex doesn’t exceed a i a_i ai (i.e. d i ≤ a i d_i≤a_i diai);
  • the diameter of the graph is maximum possible.

Input Format

The first line contains a single integer n n n ( 3 ≤ n ≤ 500 ) (3≤n≤500) (3n500) — the number of vertices in the graph.

The second line contains n n n integers a 1 , a 2 , … , a n a1,a2,…,an a1,a2,,an ( 1 ≤ a i ≤ n − 1 ) (1≤ai≤n−1) (1ain1) — the upper limits to vertex degrees.

Output Format

Print “NO” if no graph can be constructed under the given conditions.

Otherwise print “YES” and the diameter of the resulting graph in the first line.

The second line should contain a single integer m — the number of edges in the resulting graph.

The i-th of the next m lines should contain two integers v i , u i vi,ui vi,ui ( 1 ≤ v i , u i ≤ n 1≤vi,ui≤n 1vi,uin, v i ≠ u i vi≠ui vi̸=ui) — the description of the i-th edge. The graph should contain no multiple edges — for each pair ( x , y ) (x,y) (x,y) you output, you should output no more pairs ( x , y ) (x,y) (x,y) or ( y , x ) (y,x) (y,x).

Sample Input

  • 3
    2 2 2
  • 5
    1 4 1 1 1
  • 3
    1 1 1

Sample Output

  • YES 2
    2
    1 2
    2 3
  • YES 2
    4
    1 2
    3 2
    4 2
    5 2
  • No

Hint

Here are the graphs for the first two example cases. Both have diameter of 2 2 2.

Analysis

题目大意

给定n个点的度,让你将n个点连成一张连通图,要求不能有环和重边,求怎样连这张图的直径最大,且最大是多少?

算法分析

题目相当于是然你连成一棵树。思考一下,一棵树的直径最大,那不就是尽量的连成一条链嘛,是在不行就把身下的点连成侧链就好了。所以,只要把所有度大于等于二的点连成链,再取两个度为一的点连在头尾,剩下的当作侧链,就是一种最优解。

Code

#include <bits/stdc++.h>
using namespace std;
int n,m,d[507],d1[507],d2[507];
int main(){
    scanf("%d",&n);
    for (int i=1;i<=n;i++){
        scanf("%d",&d[i]);
        if (d[i]==1) d1[++d1[0]]=i;
        else d2[++d2[0]]=i,m+=d[i]-2;
    }
    if (d1[0]<2){
        printf("YES %d\n%d\n",d2[0]+d1[0]-1,n-1);
        for (int i=2;i<=d2[0];i++) printf("%d %d\n",d2[i-1],d2[i]);
        if (d1[0]) printf("%d %d\n",d1[1],d2[1]);
    }
    else{
        if (m<d1[0]-2) printf("NO\n");
        else{
            printf("YES %d\n%d\n",d2[0]+1,n-1);
            for (int i=2;i<=d2[0];i++) printf("%d %d\n",d2[i-1],d2[i]);
            printf("%d %d\n",d1[1],d2[1]);
            printf("%d %d\n",d1[2],d2[d2[0]]);
            for (int i=1,j=3;i<=n && j<=d1[0];i++){
                if (d[i]<=2) continue;
                for (;d[i]>2 && j<=d1[0];d[i]--,j++) printf("%d %d\n",d1[j],i);
            }
        }
    }
}

Postscript

这道题不禁让我想起高三的时候做的化学题,求碳链的同分异构体,各位请自行脑补。


Continue…

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值