North American Invitational Programming Contest 2018

A - Cut It Out!

Kattis - cutitout

B - Double Clique

Kattis - doubleclique

C - Flashing Fluorescents

Kattis - flashingfluorescents

D - Missing Gnomes

Kattis - missinggnomes

题意:按一定顺序给出m个数字,求n的全排列中字典序最小且满足顺序m的排列。
思路:直接模拟即可
AC代码

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 1e5+5;
int already[maxn];
bool mark[maxn];

int main() {
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 0; i < m; ++i) {
        scanf("%d", &already[i]);
        mark[already[i]] = true;
    }
    int tot = 1;
    for(int i = 0; i < m; ++i) {
        while(tot < already[i]) {
            while(mark[tot]) {
                ++tot;
            }
            if(tot < already[i]) {
                printf("%d\n", tot);
                ++tot;
            }
        }
        printf("%d\n", already[i]);
    }
    while(tot <= n) {
        if(!mark[tot])
            printf("%d\n", tot);
        ++tot;
    }
    return 0;
}

E - Prefix Free Code

Kattis - prefixfreecode

F - Probe Droids

Kattis - probedroids

题意:一个n * m()的区域,左下角是一个炮台,炮台的初始朝向是x轴正方向,然后炮台沿逆时针旋转并依次发炮,给出q()个质询,输出第 i 个被打中的位置的坐标。

思路:一开始本来想按照斜率排序,若在相同斜率上就按照与炮台距离从近到远排序。可是给出的n * m个坐标,算下来的话应该是1e12的复杂度,给了6s也是肯定不够的。

G - Rainbow Graph

Kattis - rainbowgraph
题意:给出一个n个点,m条边的无向图,但是这个图比较特殊的是每条边有颜色:R(red) G(green) B(blue), Roy和Biv是色盲,Roy看不到R(red),Biv看不到B(blue),但是他们都能看到G(green),现在他们想知道,在这个无向图中选取1~m条路,他们能否看到这个图是连通的(任意两点间可达),若不连通,输出0,若连通,输出当前选择的k条路的权值之和。
思路

H - Recovery

Kattis - recovery
题意:第一行为每行1的个数的奇偶性,第二行为每列1的个数的奇偶性,(1代表奇,0代表偶)。要求既满足,且1尽量多,且由每一行拼接成的二进制代表的数字尽量的小。若构造不出来,则输出-1。
思路:模拟,先构造出全为1的矩阵,根据行列给出的形式模拟,0尽量的往左上角放。
AC代码

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 55;
char str[maxn], ptr[maxn];
int n, m, num[maxn][maxn];

int main()
{
    scanf("%s %s", str, ptr);
    n = strlen(str);
    m = strlen(ptr);
    int numx = 0, numy = 0;
    for(int i = 0; i < n; ++i) {
        if((str[i] - '0') % 2 != m % 2)
            ++numx;
    }
    for(int i = 0; i < m; ++i) {
        if((ptr[i] - '0') % 2 != n % 2)
            ++numy;
    }
    if(numx % 2 != numy % 2) {
        printf("-1\n");
        return 0;
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            num[i][j] = 1;
        }
    }
    if(numx >= numy) {
        for(int i = n - 1; i >= 0; --i) {
            if((str[i] - '0') % 2 != m % 2) {
                num[i][0] = 0;
            }
        }
        for(int i = m - 1; i > 0; --i) {
            if((ptr[i] - '0') % 2 != n % 2) {
                for(int j = n - 1; j >= 0; --j) {
                    if(num[j][0] == 0) {
                        swap(num[j][0], num[j][i]);
                        break;
                    }
                }
            }
        }
    }
    else {
        for(int i = m - 1; i >= 0; --i) {
            if((ptr[i] - '0') % 2 != n % 2) {
                num[0][i] = 0;
            }
        }
        for(int i = n - 1; i > 0; --i) {
            if((str[i] - '0') % 2 != m % 2) {
                for(int j = m - 1; j >= 0; --j) {
                    if(num[0][j] == 0) {
                        swap(num[0][j], num[i][j]);
                        break;
                    }
                }
            }
        }
    }
    for(int i = 0; i < n; ++i) {
        for(int j = 0; j < m; ++j) {
            printf("%d", num[i][j]);
        }
        printf("\n");
    }
    return 0;
}

I - Red Black Tree

Kattis - redblacktree

题意:给出一棵树,这棵树有n个点,其中m个点为红色的。
现在给出n-1行分别是标号为2~n的点的父亲节点的编号,再给出m行为红色的点的标号,现在要选一个集合,这个集合里有且仅有k个红色节点,且集合内任意两点间不存在祖先关系,问要组成有0,1,2,...,k个红色节点的集合分别有多少种选法。

J - Winter Festival

Kattis - winterfestival

K - Zoning Houses

Kattis - zoninghouses

题意:给出n个坐标和q个质询,坐标一次标号为1~n,每次质询分别是区间l, r。现在要把区间l到r之间的坐标全部用一个边长为x的正方形框住,你可以选择忽悠至多一个坐标,问这个正方形边长最小为多少。
思路:若删除一个点,则最优方案下一定是删除x或者y坐标最小或者最大的4个点之一,用线段树维护即可。

你可能感兴趣的:(North American Invitational Programming Contest 2018)