HDU多校总结

HDU多校Multi-University Training Contest 1 总结

T1 : Maximum Multiple

题意:

每次询问一个n, 找出x, y, z 满足

x|n,y|n,z|n,x+y+z x | n , y | n , z | n , x + y + z

分析:

其实转换以下题意, 我们会有找到最基本的性质

1x+1y+1z=1 1 x + 1 y + 1 z = 1

不妨令x <= y <= z, 于是x有2,3两种取值只有
1y+1z=1223 1 y + 1 z = 1 2 或 2 3

于是大家配个方, 随便拆添项一下就好了
会发现只有(3,3,3)或者(2,4,4)或者(2,3,6)几种解, 于是分析一下n是否被4或3整除就好了

        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");

T2: Balanced Sequence

题意:

对于一个括号序列, 它的新匹配方式不一定要连续 比如 (() 可以使第一个左括号与第三个右括号匹配
题目会给你n个字符串, 你可以将它们拼接, 问最后的大字符串的匹配数最大是多少?

分析:

我们可以先对于每个串预处理, 最后每个串一定是 )))((( ) ) ) ( ( ( 之类的形式, 那么我们只要考虑这样的拼接就好了!
于是这里有一个贪心, 但是dls说正确性Unknown, 于是就只好先打了再说
我们希望浪费的左右括号尽可能小!
每一个字符串中 ) 的次数记为 l l , ) 的次数记为 r r
我们对其排序, 排序的方式是l比r小的排前面,且这些元素按 l 小的放前面 , l比r小的放后面,且 r 小的放后面!
然后就是合并, 也没什么好说的了, 就贴一份队友压哨AC的代码就好了!

#include
#define N 100005
using namespace std;
struct node
{
    int l,r;
    bool operator < (const node &c) const
    {
        return l > c.l || (l == c.l && r < c.r);
    }
}a[N];
char s[N];

int n, cur;
int main(void)
{
    int T;
    scanf("%d", &T);
    while (T --)
    {
        scanf("%d", &n);cur=0;
        int suml = 0, sumr = 0 ,ans =0;
        for (int i = 1; i <= n; ++ i)
        {
            scanf("%s", s + 1);
            int m = strlen(s + 1);
            int top = 0, L = 0, R = 0;
            for (int j = 1; j <= m; ++ j)
            {
                if (s[j] == '(') ++ top;
                if (s[j] == ')' && top > 0)
                {
                    ans += 2;
                    -- top;
                }
                else if (s[j] == ')') ++ R;
            }
            L = top;a[i].l = L;a[i].r = R;
            suml += L;sumr += R;
        }
        sort(a + 1, a + 1 + n);
        for (int i = 1; i < n; ++ i)
        {
            int l1 = a[i].l, r1 = a[i].r, l2 = a[i + 1].l, r2 = a[i + 1].r;
            if (min(l1, r2) > min(r1, l2))
            {
                ans += min(l1, r2) * 2;
                int tmpl = l2, tmpr = r1;
                if (l1 >= r2) tmpl += l1 - r2;
                else tmpr += r2 - l1;
                a[i + 1].l = tmpl;
                a[i + 1].r = tmpr;
            }
            else
            {
                ans += min(r1, l2) * 2;
                int tmpl = l1, tmpr = r2;
                if (l2 >= r1) tmpl += l2 - r1;
                else tmpr += r1 - l2;
                a[i + 1].l = tmpl;
                a[i + 1].r = tmpr;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

T3: Triangle Partition

题意:

给你3n个点, 最后输入n行, 每一行代表了3个点, 构成一个三角形, 要求n个三角形不重叠! ps: 题目保证三点不共线

直接搞个pair sort 一下就三个三个输出就好了…

就不贴代码了…

T4: Distinct Values

题目:

给你m组要求, 每次包含了一对(l, r) 意在说明 [l,r] [ l , r ] 内的元素都应是不同的, 最后输出满足要求的序列, 要求字典序最小!
如 序列长为 5, 要求 [3,5] [ 3 , 5 ] 不同, 就可以构造序列 1 1 1 2 3, 就好了

经历:

这应该来说就是贪心, 但是一开始我们的AC速度与题数还是最快的, 但是知道看见了T4, 本以为yyk应该能在两发罚时之内做出来的, 但是却被这类题目卡住了, 最后TLE收尾, 班长同学继续挺上阵, 结构最后两个人一起码T4还是码不出来, 3h过去了
队伍就垫了…虽然最后还是自己AC了此题, 但是罚时也已经爆炸了…

分析:

我们其实贪心的用一个set维护以下就好了!
比如询问有1~5, 3~7, 6~8
我们先处理处1~5的序列, 分别为1, 2, 3, 4, 5 然后处理3~7的时候, 发现3~5处理好了, 所以6~7的序列可以用1, 2 来填数, 然后no.8的位置发现数字3也可以填了 , 结果是 1 2 3 4 5 1 2 3! 于是用个set, 每次填的时候将最开头的数字填下去, 然后注意以下维护set内的元素就好了, 汗…

#include 
#define P pair
#define R register
using namespace std;
const int N = 100500;

int T, n, m, Clear, Right, ans[N];
struct node
{
    int l, r;
    friend bool operator < (node x, node y)
    {
        return (x.l != y.l) ? x.l < y.l : x.r < y.r; 
    }
}a[N];
set<int> G;

signed main()
{
    scanf("%d", &T);
    while(T--)
    {
        scanf("%d%d", &n, &m);
        Clear = Right = 0;
        G.clear();
        for(int i = 1; i <= n; i++) ans[i] = 0, G.insert(i);
        for(int i = 1; i <= m; i++)
        {
            scanf("%d%d", &a[i].l, &a[i].r);
        }
        sort(a + 1, a + 1 + m);
        for(int i = 1; i <= m; i++)
        {
            if(Right > a[i].r) continue;
            for(int j = Clear; j < a[i].l; j++) if(ans[j])
                G.insert(ans[j]);
            set<int>::iterator it = G.begin();
            for(int j = max(a[i].l, Right + 1); j <= a[i].r; j++)
            {
                ans[j] = *(G.begin());
                G.erase(G.begin());
            }
            Clear = a[i].l; Right = a[i].r;
        } 
        for(int i = 1; i <= n; i++)
        {
            if(ans[i]) printf("%d%c", ans[i],i==n?'\n':' ');
            else printf("1%c",i==n?'\n':' ');
        }
    }
    return 0;
}

小总结:

这场比赛说是有准备, 其实也是本人与队友不够给力, 也导致最后的排名不尽人意, 而比赛氛围确实无想像ACM的那般讨论的不可开交, 最后总结的还是多练习(比如找规律题, 与贪心题) 就好了.
后面的9场实在是要好好珍惜!

你可能感兴趣的:(比赛,总结)