2014多校联合五(HDU 4911 HDU 4915 HDU 4920)

HDU 4911 Inversion

题意:n个数字  通过k次相邻交换  使得逆序对数最少

思路:如果序列为 XXXABYYY  假设A和B位置互换  易知X和AB、Y和AB的逆序对数不变  换句话说一次交换最多使逆序对减少1  那么只需要求原逆序对数和k进行比较即可

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 100100
typedef __int64 ll;

int n;
ll k, ans;
int a[N], b[N], c[N];

int lowbit(int x) {
    return x & (-x);
}

void add(int x) {
    for (; x <= n; x += lowbit(x)) {
        c[x]++;
    }
}

int sum(int x) {
    int res = 0;
    for (; x > 0; x -= lowbit(x)) {
        res += c[x];
    }
    return res;
}

int main() {
    int i, j;
    while (~scanf("%d%I64d", &n, &k)) {
        for (i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        memset(c, 0, sizeof(c));
        sort(b + 1, b + n + 1);
        ans = 0;
        for (i = 1; i <= n; i++) {
            j = lower_bound(b + 1, b + n + 1, a[i]) - b;
            ans += sum(n) - sum(j);
            add(j);
        }
        if (ans > k)
            printf("%I64d\n", ans - k);
        else
            printf("0\n");
    }
    return 0;
}

HDU 4915 Parenthese sequence

题意:?可以代表(或)  那么输入的字符串能构造出几种合法的括号序列呢  输出无解、唯一解、多解

思路:这题是我YY的…  首先我们可以计算出(和)应该填几个  如果计算出?不满足我们要填的东西  那么必然无解  接着有一种最简单的解  那就是把靠左边的问号全变成‘(’(注意个数)剩下的变成‘)’  如果这样构造完的字符串都不是合法的  那么一定没有合法的解  然后开始YY…  发现我们填上的最中间的(和)通过交换可以影响最小  而且两边的括号很可能可以满足它们  所以我们将构造出的序列中我们填上的最中间的两个括号交换  最后验证一下新串是否合法
 合法就是多解  否则唯一解  注意!!  有可能我们根本不能交换!!  因为我们全填的是(或)

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 1000010

char str[N], f[N];
int n, num, g1, g2;

int ff(int x) {
    if (x < 0)
        return -x;
    return x;
}

int main() {
    int i, j, tmp;
    while (~scanf("%s", str)) {
        n = strlen(str);
        for (i = num = g1 = g2 = 0; i < n; i++) {
            if (str[i] == '?')
                num++;
            else if (str[i] == '(')
                g1++;
            else
                g2++;
        }
        tmp = ff(g1 - g2);
        if (num < tmp || (num - tmp) % 2 != 0) {
            puts("None");
            continue;
        }
        if (g1 < g2)
            tmp = tmp + (num - tmp) / 2;
        else
            tmp = (num - tmp) / 2;
        for (i = j = 0; i < n; i++) {
            if (str[i] == '?') {
                j++;
                if (j <= tmp)
                    str[i] = '(';
                else
                    str[i] = ')';
                if (j < tmp || j == tmp + 1)
                    f[i] = '(';
                else
                    f[i] = ')';
            } else
                f[i] = str[i];
        }
        for (i = j = 0; i < n; i++) {
            if (str[i] == '(')
                j++;
            else
                j--;
            if (j < 0)
                break;
        }
        if (i < n) {
            puts("None");
            continue;
        }
        if (tmp == 0 || tmp == num) {
            puts("Unique");
            continue;
        }
        for (i = j = 0; i < n; i++) {
            if (f[i] == '(')
                j++;
            else
                j--;
            if (j < 0)
                break;
        }
        if (i < n)
            puts("Unique");
        else
            puts("Many");
    }
    return 0;
}

HDU 4920 Matrix multiplication

题意:求矩阵乘法  最后所有数字%3

思路:分块!  如果n3我们会T的话  那么我们可以把任务分成两次去做  类似于前缀和或分治的优化思想!

首先分块7个数字一组  然后矩阵相乘就变成了块相乘  既然块相乘的复杂度我们可以接受  那么剩下的就是——如果给你两个块  如何快速计算他们的积  打表!  我们利用3进制数表示状态dp打出任何两个块相乘的积  最后利用dp的结果计算即可

代码:

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define M 810

int n, N;
int f[2200][2200];
int a[M][M], b[M][M], c[M][M];
int A[M][M], B[M][M];

int read() {
    char ch;
    bool ok = 0;
    int res = 0;
    for (;;) {
        ch = getchar();
        if (ch >= '0' && ch <= '9')
            res = res * 10 + ch - '0', ok = 1;
        else if (ok)
            return res % 3;
    }
}

int solve(int a, int b) {
    int i = 7, res = 0;
    while (i--) {
        res += (a % 3) * (b % 3);
        a /= 3;
        b /= 3;
    }
    return res % 3;
}

int main() {
    int i, j, k;
    for (i = 0; i < 2187; i++)
        for (j = 0; j < 2187; j++)
            f[i][j] = solve(i, j);
    while (~scanf("%d", &n)) {
        N = (n - 1) / 7 + 1;
        for (i = 0; i < n; i++) {
            int cnt = 0;
            int tmp = 0;
            for (j = 0; j < n; j++) {
                cnt++;
                a[i][j] = read();
                tmp = tmp * 3 + a[i][j];
                if (cnt == 7) {
                    A[i][j / 7] = tmp;
                    tmp = 0;
                    cnt = 0;
                }
            }
            if (cnt > 0)
                A[i][N - 1] = tmp;
        }
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++) {
                b[i][j] = read();
                c[i][j] = 0;
            }
        for (j = 0; j < n; j++) {
            int cnt = 0;
            int tmp = 0;
            for (i = 0; i < n; i++) {
                cnt++;
                tmp = tmp * 3 + b[i][j];
                if (cnt == 7) {
                    B[i / 7][j] = tmp;
                    tmp = 0;
                    cnt = 0;
                }
            }
            if (cnt > 0)
                B[N - 1][j] = tmp;
        }
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++)
                for (k = 0; k < N; k++)
                    c[i][j] += f[A[i][k]][B[k][j]];
        for (i = 0; i < n; i++)
            for (j = 0; j < n; j++) {
                printf("%d", c[i][j] % 3);
                if (j == n - 1) {
                    putchar('\n');
                } else
                    putchar(' ');
            }
    }
    return 0;
}

PS:GXX姐姐出的题还是很良心的  感觉这次比赛值得进一步去做!  虽然弱弱的自己比赛只出了3题…TAT

2014多校联合五(HDU 4911 HDU 4915 HDU 4920),布布扣,bubuko.com

时间: 2024-10-26 13:06:16

2014多校联合五(HDU 4911 HDU 4915 HDU 4920)的相关文章

2014多校第五场1001 || HDU 4911 Inversion (归并求逆序数)

题目链接 题意 : 给你一个数列,可以随意交换两相邻元素,交换次数不超过k次,让你找出i < j 且ai > aj的(i,j)的对数最小是多少对. 思路 : 一开始想的很多,各种都想了,后来终于想出来这根本就是求逆序数嘛,可以用归并排序,也可以用树状数组,不过我们用树状数组做错了,也不知道为什么.求出逆序数来再减掉k次,就可以求出最终结果来了.求逆序数链接1,链接2 1 #include <stdio.h> 2 3 int left[250003], right[250003];

2014多校联合六(HDU 4923 HDU 4925 HDU 4927 HDU 4930)

HDU 4923 Room and Moor 题意:给出A序列  求满足题目所写的B序列  使得方差最小 思路:可以想到最后的结果中  B序列的值一定是一段一段的  那么我们可以类似贪心去搞  对于一段序列我们可以求出什么样的b值使得方差最小  即序列中1的个数除以序列长度  又因为B是单调的  可以用一个单调栈去模拟  复杂度远远小于n^2  不要被吓怕- 代码: #include<cstdio> #include<cstring> #include<algorithm&g

2014多校联合三 (HDU 4888 HDU 4891 HDU 4893)

HDU 4891 The Great Pan 签到题  他怎么说你就怎么做就好了  注意做乘法时候会爆int 代码: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; typedef long long LL; int n; char s[2000000]; int flag1, flag2, sp, ansflag;

2014多校联合八(HDU 4945 HDU 4946 HDU 4948 HDU 4950 HDU 4951 HDU 4952)

HDU 4945 2048 题意:给你一堆数字  问有几个子集可以拼出2048 思路: 拼数字的规则相当于让数字乘二  所以不是2^i的数字不会拼出2048  那么这些数可选可不选  即为2^cnt种可能 之后只要计算出有几个子集不可能拼出2048即可  不过简单的直接dp是2048*100000的复杂度的  会TLE 所以要变成先枚举元素  再枚举该种元素个数  再枚举2048种状态  然后利用组合求(组合里需要逆元) 为什么这样快?  因为比如枚举2^5这个元素的时候  最多取2^6个  枚

2014多校第五场1010 || HDU 4920 Matrix multiplication(矩阵乘法优化)

题目链接 题意 : 给你两个n*n的矩阵,然后两个相乘得出结果是多少. 思路 :一开始因为知道会超时所以没敢用最普通的方法做,所以一直在想要怎么处理,没想到鹏哥告诉我们后台数据是随机跑的,所以极端数据是不可能会有的,而我们一开始一直在想极端数据能接受的方法......后来看了鹏哥的做法,就是把是0的地方都跳过就可以了,用矩阵保存前一个非0数的位置是多少.二师兄给我看了一个代码,人家根本没用别的优化,直接将最里层k的循环提到了最外层,然后就AC了,对此我表示无语. 1 #include <cstd

2014多校联合四(HDU 4901 HDU 4902 HDU 4905)

HDU 4901 The Romantic Hero 题意: 一串数字a  找一个位置分开  前面为S'后面为T'  从这两个集合中分别选出子集S和T  使得S中元素的"异或"值等于T中元素的"且"值  问一共几种方案 思路: 由于a[i]只有1024  那么无论怎么运算都不可能大于2047  又因为S和T有一个明显的分界  所以我们可以想到利用dp分左右两边处理  令l[i][j]表示从左到i位置且一定选取a[i]的情况下异或值为j的方案数  r[i][j]类似

2014多校联合七(HDU 4937 HDU 4938 HDU 4939 HDU 4941)

好几天没写题解了- 都怪我太弱  补题补不动- HDU 4937 Lucky Number 题意:一个数字如果只有3456这四种数字组成  那么这个数字是幸运的  问  给出一个x  它在几种进制下是幸运的  如果无穷输出-1 思路: 分类讨论  如果x是3或4或5或6  那么一定有无穷个进制满足(从十进制开始-)  直接输出-1 除去上述情况  那么我们可以将一个数字写成这样 a0 + a1*base + a2*base^2 +... = x 那么如果base的最高次只有1次或2次时  就是简

hdu 4865 Peter&amp;#39;s Hobby(2014 多校联合第一场 E)

Peter's Hobby Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 545    Accepted Submission(s): 237 Problem Description Recently, Peter likes to measure the humidity of leaves. He recorded a leaf

hdu 4865 Peter&#39;s Hobby(2014 多校联合第一场 E)

题意:已知昨天天气与今天天气状况的概率关系(wePro),和今天天气状态和叶子湿度的概率关系(lePro)第一天为sunny 概率为 0.63,cloudy 概率 0.17,rainny 概率 0.2.给定n天的叶子湿度状态,求这n天最可能的天气情况 分析:概率dp设 dp[i][j] 表示第i天天气为j的最大概率,pre[i][j]表示第i天天气最可能为j的前一天天气,dp[i][j]=max(dp[i-1][k]+log(wePro[k][j])+log(lePro[j][lePos[i]]