题解之前
愉悦的要火十人ACM大赛即将开始!
飞扬的小鸟
以为是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; }
复杂的道路
看见异或,首先想到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; }
紧凑的代码
手动说再见~
我是真的服了。
不会做。
作为每年都有省队的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