机房测试9.15

题解之前

愉悦的要火十人ACM大赛即将开始!

飞扬的小鸟

1447768-20180915152540567-151552109.png

1447768-20180915152556582-584362597.png

以为是NOIP2014

发现实则不然

容易发现,从(0,0) 走到(x,y) 的点击次数是(x+y)/2,要点击次数最少,则到达终点时y 最小,所以只需维护小鸟能到达哪些点。

可以发现,如果能到达(x0,y1) 和(x0,y2)(不妨设y1 < y2),那么一定能到达(x0,y1),(x0,y1+2)......(x0,y2-2),(x0,y2),因为每多点一次y 就增大2,那么对于每个x,小鸟能到达的位置都是一个区间内y 的奇偶性相同的所有位置,所以可以递推维护在每个障碍处y 的取值范围[li,ri],如果发现某时y 没有合法取值则输出无解。但需特判当q-p = 2 时(此时p = ?1,q = 1)一定无解,其余情况可以不用考虑边界。时间复杂度O(n)

#define FN "bird"
#include <cstdio>
#include <cctype>
typedef bool bnt;
typedef void vnt;
struct buf
{
    operator int()
    {
        register int c = getchar(), x = 0; register bnt s = false;
        for (;!isdigit(c); c = getchar()) s |= c == '-';
        for (; isdigit(c); c = getchar()) x = x * 10 - '0' + c;
        return s ? -x : x;
    }
} fio;
int p, q, m, n, x, a, b, c, l, r;
inline vnt nxt()
{
    l -= a - x, r += a - x;
    if (l <= b) l += (((b - l) >> 1) + 1) << 1;
    if (r >= c) r -= (((r - c) >> 1) + 1) << 1;
}
int main()
{
    freopen(FN ".in", "r", stdin);
    freopen(FN ".out", "w", stdout);
    p = fio, q = fio, m = fio, n = fio;
    if (q - p == 2)
        puts("-1");
    else
    {
        for (x = 0; n-- && x < m; x = a)
        {
            a = fio, b = fio, c = fio;
            if (a > m) a = m, b = p, c = q;
            nxt();
            if (l > r) return puts("-1"), 0;
            if (!n && a < m) x = a, a = m, b = p, c = q, nxt();
        }
        printf("%d\n", (x + l) >> 1);
    }
    return 0;
}

复杂的道路

1447768-20180915153537377-107033629.png

1447768-20180915153546845-1378777920.png

看见异或,首先想到trie树,看见连接成一棵树,就想到最小生成树。

所以trie树+kruskal就可以了。

很棒!

#include<bits/stdc++.h>
#define FN "road"

const int oo=1e9+7;
const int maxn=2e5+5;
long long ans,cost;

struct Trie {
        
        int ch[maxn<<5][2];
        int siz[maxn<<5];
        int val[maxn<<5];
        int sz,up=30;
        
        void init() {
            sz=1;
            memset(ch[0],0,sizeof(ch[0]));
        }
        
        void insert(int x) {
            int u=0;
            for(int i=up;i>=0;i--) {
                int c=((x>>i)&1);
                if(!ch[u][c]) {
                    memset(ch[sz],0,sizeof(ch[sz]));
                    val[sz]=0;
                    ch[u][c]=sz++;
                }
                u=ch[u][c];
            }
            val[u]=x;
        }
        
        int getSize(int x) {
            if(!ch[x][0]&&!ch[x][1]) return siz[x]=1;
            if(ch[x][0]) siz[x]+=getSize(ch[x][0]);
            if(ch[x][1]) siz[x]+=getSize(ch[x][1]);
            return siz[x];
        }
        
        void dfs(int x) {
            if(ch[x][0]) dfs(ch[x][0]);
            if(ch[x][1]) dfs(ch[x][1]);
            if(ch[x][0]&&ch[x][1]) {
                cost=oo;
                int lson=ch[x][0];
                int rson=ch[x][1];
                if(siz[lson]<siz[rson])
                    calc(lson,x);
                else 
                    calc(rson,x);
                ans+=cost;
            }
        }
        
        void calc(int x,int pre) {
            if(ch[x][0]) calc(ch[x][0],pre);
            if(ch[x][1]) calc(ch[x][1],pre);
            if(!ch[x][0]&&!ch[x][1]) {
                int now=query(val[x],pre);
                if(cost>(val[now]^val[x]))
                    cost=(val[now]^val[x]);
            }
        }
        
        int query(int x,int pre) {
            int u=0;
            for(int i=up;i>=0;i--) {
                int c=((x>>i)&1);
                if(!ch[u][c]) c=1-c;
                if(u==pre) c=1-c;
                u=ch[u][c];
            }
            return u;
        }
        
}trie;

int main() {
    freopen(FN".in","r",stdin);
    freopen(FN".out","w",stdout);
    int n;
    scanf("%d",&n);
    trie.init();
    for(int i=1;i<=n;i++) {
        int x;
        scanf("%d",&x);
        trie.insert(x);
    }
    trie.getSize(0);
    trie.dfs(0);
    printf("%lld\n",ans);
    return 0;
}

紧凑的代码

1447768-20180915153906653-43385632.png
1447768-20180915153922019-1384268946.png
1447768-20180915153935241-1461368829.png
1447768-20180915153947574-1096855490.png
1447768-20180915153959969-925030763.png
1447768-20180915154009774-16362412.png

手动说再见~

我是真的服了。

不会做。

作为每年都有省队的CDQZ,最高分10分。

出题人称略高于NOIP2017时间复杂度。

我失去梦想了。

#define FIO "code"
#include <cstdio>
#include <cctype>
#define L_MAX 112640
#define O_MAX 55
#define N_MAX 56
#define C_MAX 127
inline bool is_name(int c)
{
    return isalnum(c) || c == '_' || c == '$';
}
char a[L_MAX + 1],
    * i = a, * j = i, * k = a, * l = k; // [i, j): last word; [k, l): current word
const char * op[O_MAX] = {
    "((", "))", "[[", "[<:", "]]", "]:>", "{{", "{<%", "}}", "}%>",
    "##", "#%:", "..", "!!", "~~", ",,", ";;",
    "++", "=+=", "+++", "--", "=-=", "---", "**", "=*=",
    "&&", "=&=", "&&&", "||", "=|=", "|||", "^^", "=^=",
    "<<", "=<=", "<<<", "=<<=", ">>", "=>=", ">>>", "=>>=",
    "==", "===", "=!=", "??", "::", ":::",
    "''", "\"\"", "//", "=/=", "c//", "C/*", "%%", "=%=",
};
int n = 1, trie[N_MAX + 1][C_MAX], type[N_MAX + 1],
    r, // is forced to break line?
    s, t; // type of [i, j), [k, l); [0] => empty, [1] => name, [c] => type
inline void insert(int t, const char * s)
{
    static int u;
    for (u = 1; *s; u = trie[u][int(*s++)])
        if (!trie[u][int(*s)]) trie[u][int(*s)] = ++n;
    type[u] = t;
}
inline bool check()
{
    return s == ' ' || 
    (s == 1 && t == 1) || 
    (s == '/' && (*k == '/' || *k == '*')) || 
    (s == ':' && *k == ':') || 
    (s == '+' && *k == '+') || 
    (s == '-' && *k == '-') || 
    (s == '<' && *k == '<') || 
    (s == '>' && *k == '>') || 
    (s == '&' && *k == '&') || 
    (s == '<' && *k == ':') || 
    (s == '%' && *k == ':') || 
    //
    (s == 1 && t == '"' && j != k && \
    ((j - i == 1 && (*i == 'u' || *i == 'U' || *i == 'L')) || \
        (j - i == 2 && *i == 'u' && *(i + 1) == '8')));
}
inline void output(int c = 0)
{
    if (c) putchar(c);
    i = k, j = l, s = t;
    while (k < l) putchar(*k++);
}
inline char seek(char * l)
{
    while (*l == '\\' && !*(l + 1)) gets(l);
    return *l;
}
inline void seek_char(char *& l)
{
    for (seek(l); *l != '\'' || *(l - 1) == '\\'; seek(++l));
    ++l;
}
inline void seek_str(char *& l)
{
    for (seek(l); *l != '"' || *(l - 1) == '\\'; seek(++l));
    ++l;
}
inline void seek_comment_line(char *& l)
{
    for (seek(l); *l; seek(++l));
}
inline void seek_comment_block(char *& l)
{
    do
    {
        ++l;
        while (!seek(l))
            *l++ = '\n', gets(l);
        seek(l);
    }
    while (*l != '/' || *(l - 1) != '*');
    ++l;
}
inline int seek_word(char *& k, char *& l)
{
    static int t, u;
    do
    {
        k = l;
        while (isspace(seek(k)))
            ++k;
        if (!*(l = k))
            t = 0;
        else if (is_name(*l)) // names | numbers
            for (t = 1, ++l; is_name(seek(l)); ++l);
        else
        {
            for (u = 1; seek(l) && trie[u][int(*l)]; u = trie[u][int(*l++)]);
            t = type[u];
            switch (t)
            {
            case '\'': seek_char(l); break;
            case '"':  seek_str(l); break;
            case 'c':  seek_comment_line(l); break;
            case 'C':  seek_comment_block(l); break;
            }
        }
    }
    while (t == 'c' || t == 'C');
    return t;
}
int main()
{
    freopen(FIO ".in", "r", stdin);
    freopen(FIO ".out", "w", stdout);
    for (int o = 0; o < O_MAX; ++o)
        insert(*op[o], op[o] + 1);
    r = '^';
    while (gets(l))
    {
        if (r == '\n') putchar('\n'), r = s = 0, i = j;
        t = seek_word(k, l);
        if (k == l)
            continue;
        else if (t != '#')
            output(check() ? ' ' : 0);
        else
        {
            output(s == 0 ? 0 : '\n');
            r = '\n', t = seek_word(k, l), output();
            if (*i == 'd') // is #define?
            {
                t = seek_word(k, l), output(' ');
                if (seek(l) != '(') s = ' ';// is function-like macro?
            }
        }
        while ((t = seek_word(k, l)))
            output(check() ? ' ' : 0);
    }
    return 0;
}

正在紧锣密鼓的进行研究。

好像大家放弃了对于要火算法的研究。

转载于:https://www.cnblogs.com/LoLiK/p/9651114.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值