A题

给出n,求xyz的最大值,要求n = x + y + z 且 n 能整除x y z,没有输出-1

解:1 = 1/3 + 1/3 + 1/3 = 1/2 + 1/4 + 1/4,只要能被3/4整除就有解

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

typedef long long ll;
ll T,n;

int main()
{
    scanf("%lld",&T);
    while(T--)
    {
        scanf("%lld",&n);
        if(n % 3 == 0) printf("%lld\n",(n / 3) * (n / 3) * (n / 3));
        else if(n % 4 == 0) printf("%lld\n",(n / 2) * (n / 4) * (n / 4));
        else printf("-1\n");
    }
    return 0;
}

 

B题 给你n个括号字符串,排序这些括号字符串,怎么排序能使其配对最多并输出总共有几个括号可以参与配对

解:预处理每个字符串,计算出每个字符串本身可以配对几个,有几个'('和')'还没进行配对(栈)

        排序(谁能对形成配对的贡献大,字符串里 '(' 出现次数比 ')'多,它比较适合排前面,能够使自己对整个配对做出的贡献最大,a和b比较的话,如果a和b都是'('贡献大的话,谁的')'小就排前面,因为相对来说')'的要往后排,相对贡献会大一些)

 

D题

构造一个序列,使得m个给定区间内的数字各不相同并且序列的字典序最小

解:区间位置有相离,相交,重合3种

      先将区间按左端点排个序

      重合不需要考虑,因为满足大区间的也满足小区间

      相交:前一个区间先选,后一个区间的数字从不重合部分开始,依次选重合区间没有选过的数字

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

struct node
{
    int l,r;
}a[100010];

int T,n,m,k,l,r;
int ans[100010],num[100010];

bool cmp(node k,node p)
{
    if(k.l == p.l) return k.r > p.r;
    return k.l < p.l;
}

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(ans,0,sizeof(ans));
        memset(num,0,sizeof(num));
        for(int i = 0;i < m; ++i) scanf("%d%d",&a[i].l,&a[i].r);
        sort(a,a + m,cmp);
        for(int j = a[0].l;j <= a[0].r; j++)   
            ans[j] = j - a[0].l + 1;
        l = a[0].l;
        r = a[0].r;
        for(int i = 1;i < m; ++i)
        {
            if(r >= a[i].r) continue;
            k = 1;
            if(a[i].l <= r)   //相交区间
            {
                for(int j = a[i].l;j <= r; ++j)
                    num[ans[j]] = i;
                for(int j = r + 1;j <= a[i].r; ++j)
                {
                    while(num[k] == i) ++k;
                    ans[j] = k++;
                }
            }
            else   //不相交区间
                for(int j = a[i].l;j <= a[i].r; ++j)
                    ans[j] = k++;
            l = a[i].l;
            r = a[i].r;
        }
        for(int i = 1;i <= n; ++i)
        {
            if(i > 1) printf(" ");
            if(ans[i]) printf("%d",ans[i]);
            else printf("1");
        }
        printf("\n");
    }
    return 0;
}

ps:正解:利用set的去重和排序功能,利用tot标记一下当前可入set的左界(可重复利用),pre数组记录的是区间左界

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

int T,n,m,l,r,tot;
set<int>s;
int ans[100100],pre[100100];

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1;i <= n; ++i) pre[i] = i,s.insert(i);
        for(int i = 0;i < m; ++i)
        {
            scanf("%d%d",&l,&r);
            pre[r] = min(pre[r],l);
        }
        for(int i = n - 1;i >= 1; --i)
            pre[i] = min(pre[i],pre[i + 1]);
        tot = 1;
        for(int i = 1;i <= n; ++i)
        {
            while(tot < pre[i]) s.insert(ans[tot++]);
            ans[i] = *s.begin();
            s.erase(ans[i]);
        }
        for(int i = 1;i < n; ++i)
            printf("%d ",ans[i]);
        printf("%d\n",ans[n]);
    }
    return 0;
}

K题   

给出西八区的时间,求其他时区的时间

解:极度玄学...咱也不知道为啥错...咱也不知道改了哪里就对了

教训:避免浮点数的加减,全部换算成分钟

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

int T,n,m,len;
string s;
double t,f;

int main()
{
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d UTC%lf",&n,&m,&t);
        int k = n * 60 + m - 8 * 60;
        int p = t * 10;
        k += p * 6;
        while(k < 0) k += 24 * 60;
        k %= (24 * 60);
        m = k % 60;
        n = k / 60;
        printf("%02d:%02d\n",n,m);
    }
    return 0;
}