2018 Multi-University Training Contest 1(补题)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_38749759/article/details/81273077

又到了hdu多校的季节,废话不多时,开始上代码

A题

Maximum Multiple

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3985    Accepted Submission(s): 926

Problem Description

Given an integer n, Chiaki would like to find three positive integers x, y and z such that: n=x+y+z, xn, yn, zn and xyz is maximum.

Input

There are multiple test cases. The first line of input contains an integer T (1≤T≤106), indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤106).

Output

For each test case, output an integer denoting the maximum xyz. If there no such integers, output −1 instead.

Sample Input

3 1 2 3

Sample Output

-1 -1 1

题目大意:给你一个数n,让你自己找三个数x,y,z,满足n=x+y+z, xn, yn, zn(这三个数都能整除n),求出xyz乘积的最大值

思路:找规律,多写几个数找一下,你就会~~神奇的发现~~~这个n只有是三或四的倍数才能满足上述要求,所以找到数字n后,把它拆分,拆出三个数使它们的乘积最大值即可,其它的时候是不可能存在的,所以直接输出-1。

代码如下

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;


int main()
{
    ios::sync_with_stdio(false);
    LL T;
    cin>>T;
    while(T--){
        LL n,ans;
        ans=0;
        cin>>n;
        if(n%3==0)
            ans=(n/3)*(n/3)*(n/3);
        else if(n%4==0)
        {
            ans=(n/2)*(n/4)*(n/4);
        }
        else
            ans=-1;
        cout<<ans<<endl;
    }
    return 0;
}

B题

Balanced Sequence

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 4879    Accepted Submission(s): 1262

Problem Description

Chiaki has n strings s1,s2,…,sn consisting of '(' and ')'. A string of this type is said to be balanced:
+ if it is the empty string
+ if A and B are balanced, AB is balanced,
+ if A is balanced, (A) is balanced.
Chiaki can reorder the strings and then concatenate them get a new string t. Let f(t) be the length of the longest balanced subsequence (not necessary continuous) of t. Chiaki would like to know the maximum value of f(t) for all possible t.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤105) -- the number of strings.
Each of the next n lines contains a string si (1≤|si|≤105) consisting of `(' and `)'.
It is guaranteed that the sum of all |si| does not exceeds 5×106.

Output

For each test case, output an integer denoting the answer.

Sample Input

2

1

)()(()(

2

)

)(

Sample Output

4 
2
Source
2018 Multi-University Training Contest 1 

题目大意

给你n个包含’(‘与’)’的字符串,可以将这些字符串任意排序,求所有排序中,子序列是正规括号序列的最大长度。

思路

首先我们对所有的字符串找到通过stack找到所有的串内正规括号子序列

(就是原串中自然形成的“()”的括号,并把他们从原串中删除,每有一对用ans统计)

之后剩下的串只有三种可能:
1. 只包含’(’
2. 先是一串’)’然后再是一串’(’
3. 只包含’)’
然后,按照第一类,第二类,第三类的顺序放置串。对于第二类内的排序,首先按照’(‘个数贡献正负排序,’)’个数小于’(‘个数则贡献为正,贡献是正的则排前面。然后正贡献的串,我们按照’)’个数从小到大排。负贡献的串,我们按照’(‘个数从大到小排。对于排序完的串,我们从前往后模拟记录一下即可。

最后答案是求满足的长度所有就是ans*2;

代码如下

#include<cstdio>
#include<cstring>
#include<stack>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long LL;
const int maxn=1e5+10;
struct node{
   int a,b;
}p[maxn];
bool cmp(struct node x,struct node y)
{
    if(x.a+x.b>=0&&y.a+y.b>=0)
        return x.b>y.b;
    else if(x.a+x.b>=0)
        return true;
    else if(y.a+y.b>=0)
        return false;
    else
        return x.a>y.a;
}
stack<char> sk;
char str[maxn];
vector<node> vec1,vec2,vec3;
int ans;
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
        while(!sk.empty()) sk.pop();
        vec1.clear();vec2.clear();vec3.clear();
        ans=0;
        int n, step=0;
        scanf("%d",&n);
        for(int i=0;i<n;i++){
            scanf("%s",str);
            for(int j=0;str[j]!='\0';j++){
                if(str[j]=='(')
                    sk.push(str[j]);
                else if(!sk.empty()&&sk.top()=='('){
                    sk.pop();   ans++;    
                }
                else
                    sk.push(str[j]);
            }
            int x,y;   x=y=0;
            while(!sk.empty()){
                if(sk.top()=='(')
                    x++;
                else
                    y--;
                sk.pop();
            }
            p[i].a=x;     p[i].b=y;
            if(x&&y==0)
                vec1.push_back(p[i]);
            else if(y&&x==0)
                vec3.push_back(p[i]);
            else
                vec2.push_back(p[i]);
        }
        for(int i=0;i<vec1.size();i++)
            step+=vec1[i].a;
        sort(vec2.begin(),vec2.end(),cmp);
        for(int i=0;i<vec2.size();i++){
            if(step<0)
                step=0;
            ans+=min(step,-vec2[i].b);
            if(step+vec2[i].b<0){
                step=vec2[i].a;
                continue;
            }
            step+=vec2[i].a+vec2[i].b;//-(+);
        }
        for(int i=0;i<vec3.size();i++)
        {
            if(step<0)
                step=0;
            ans+=min(step,-vec3[i].b);
            if(step+vec3[i].b<0)
            {
                step=0;
                break;
            }
            step+=vec3[i].b;
        }
        printf("%d\n",ans*2);
    }
    return 0;
}

C题

Triangle Partition

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)
Total Submission(s): 1486    Accepted Submission(s): 752

Problem Description

Chiaki has 3n points p1,p2,…,p3n. It is guaranteed that no three points are collinear.
Chiaki would like to construct n disjoint triangles where each vertex comes from the 3n points.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains an integer n (1≤n≤1000) -- the number of triangle to construct.
Each of the next 3n lines contains two integers xi and yi (−109≤xi,yi≤109).
It is guaranteed that the sum of all n does not exceed 10000.

Output

For each test case, output n lines contain three integers ai,bi,ci (1≤ai,bi,ci≤3n) each denoting the indices of points the i-th triangle use. If there are multiple solutions, you can output any of them.

Sample Input

1

1

1 2

2 3

3 5

Sample Output

1 2 3

Source

2018 Multi-University Training Contest 1

题目大意

给3n个点,其中不可能存在任意三点共线的情况,让你在其中建n个三角形,点不能重复使用,三角形不能相互覆盖

思路

题目条件保证了三个点一定不在同一直线上,对坐标进行排序,先x后y,从小到大,每三个点构成一个三角形。输出构成三角形点的编号。

代码如下

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int maxn=30000;
struct node{
    LL x,y;
    LL id;
}p[maxn];
bool cmp(struct node a,struct node b){
    if(a.x==b.x)
        return a.y<b.y;
    return a.x<b.x;
}
int main()
{
    ios::sync_with_stdio(false);
    int T;
    cin>>T;
    while(T--){
        int n ;
        cin>>n;
        for(int  i=0;i<3*n;i++)
        {
            cin>>p[i].x>>p[i].y;
            p[i].id=i+1;
        }
        sort(p,p+3*n,cmp);
        for(int  i=0;i<3*n;i++)
            cout<<p[i].id<<" ";
        cout<<endl;
    }
    return 0;
}

D题

Distinct Values

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 3894    Accepted Submission(s): 1303

Problem Description

Chiaki has an array of n positive integers. You are told some facts about the array: for every two elements ai and aj in the subarray al..r (li<jr), aiaj holds.
Chiaki would like to find a lexicographically minimal array which meets the facts.

Input

There are multiple test cases. The first line of input contains an integer T, indicating the number of test cases. For each test case:
The first line contains two integers n and m (1≤n,m≤105) -- the length of the array and the number of facts. Each of the next m lines contains two integers li and ri (1≤lirin).
It is guaranteed that neither the sum of all n nor the sum of all m exceeds 106.

Output

For each test case, output n integers denoting the lexicographically minimal array. Integers should be separated by a single space, and no extra spaces are allowed at the end of lines.

Sample Input

3

2 1

1 2

4 2

1 2

3 4

5 2

1 3

2 4

Sample Output

1 2

1 2 1 2

1 2 3 1 1

Source

2018 Multi-University Training Contest 1

题目:构造一个字典序最小的序列,满足给的m个条件,每个条件一个区间(l , r)内没有重复出现的数字。

思路:最近在学习树状数组,所以我是边模拟边用二分+树状数组维护的。

代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=100000;
int arr[maxn];
int ans[maxn];
int sz[maxn];
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int d)
{
    while(x <= maxn)
    {
        sz[x] = sz[x]+d;
        x = x+lowbit(x);
    }
}
int sum(int x)
{
    int res = 0;
    while(x > 0)
    {
        res = res+sz[x];
        x = x-lowbit(x);
    }
    return res;
}

int pos(int l,int r)
{
    if(sum(r)-sum(l-1)==r-l+1)//
        return r+1;
    while(l<=r-1)
    {
        int mid=(l+r)/2;
         if(sum(mid)-sum(l-1)<mid-l+1)//
            r=mid;
        else 
            l=mid+1;
    }
    return l;     
}


int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d %d",&n,&m);
        memset(sz,0,sizeof(sz));
        for(int i=1;i<=n;i++)
            arr[i]=i;
        for(int i=0;i<m;i++){
            int l,r;
            scanf("%d%d",&l,&r);
            arr[l]=max(arr[l],r);
        }
        int ed;
        ed=0;
        for(int i=1;i<=n;i++)
        {
            if(arr[i]<=ed){
                update(ans[i],-1);
                continue;
            }
            int k=ed+1;
            ed=arr[i];
            for(;k<=ed;k++){
                ans[k]=pos(1,k-1);
                update(ans[k],1);
            }
            update(ans[i],-1);
        }
        printf("%d",ans[1]);
        for(int i=2;i<=n;i++)
            printf(" %d",ans[i]);
        printf("\n");
    }
    return 0;
}

K题

Time Zone

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2664    Accepted Submission(s): 841

Problem Description

Chiaki often participates in international competitive programming contests. The time zone becomes a big problem.
Given a time in Beijing time (UTC +8), Chiaki would like to know the time in another time zone s.

Input

There are multiple test cases. The first line of input contains an integer T (1≤T≤106), indicating the number of test cases. For each test case:
The first line contains two integers a, b (0≤a≤23,0≤b≤59) and a string s in the format of "UTC+X'', "UTC-X'', "UTC+X.Y'', or "UTC-X.Y'' (0≤X,X.Y≤14,0≤Y≤9).

Output

For each test, output the time in the format of hh:mm (24-hour clock).

Sample Input

3

11 11 UTC+8

11 12 UTC+9

11 23 UTC+0

Sample Output

11:11

12:12

03:23

Source

2018 Multi-University Training Contest 1

题目大意:你在东8区进行时区转化

思路:时间划为分钟,进行转化

代码如下

#include <iostream>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
#define eps 1e-10
typedef long long LL;
const int maxn=10000;

int main()
{
    
    int T;
    int Hour;
    int Min;
    char x;
    float hh;
    cin>>T;
    while(T--){
        scanf("%d %d UTC%c%f",&Hour,&Min,&x,&hh);
        Min+=Hour*60;
        int H,M;
        if(x=='+')
            hh-=8;
        else
            hh=4+(12-hh);
        if(hh>0)
            Min+=(int)(hh*60+0.1);
        else
            Min+=(int)(hh*60-0.1)+24*60;
        H=(Min/60)%24;
        M=(Min%60);
        printf("%02d:%02d\n",H,M);
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_38749759/article/details/81273077