平时三测
Posted edsheeran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了平时三测相关的知识,希望对你有一定的参考价值。
题解:
第一题:每个柱子可以到达的位置是可求的一个区间,我们得到区间,并和下一个柱子的限制取交集,得到一个新区间,这样一直做下去,就可以得到最终答案的区间,我们肯定贪心走到最低点,知道了这个坐标,就可以O(1)得到答案,不用在考虑中间是怎么走的(我就是这点没有想到,然后去暴力DP了);最后在注意一下奇偶的问题,比如x%2 == 0时,他的y一定也是偶数;
#include<bits/stdc++.h> using namespace std; const int M = 1000009; int a[M], b[M], c[M]; #define For(a, b, c) for(int a=b;a<=c;a++) int read(){ int x=0,f=1;char c=getchar(); while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();} while(c>=‘0‘&&c<=‘9‘){x=x*10+c-‘0‘;c=getchar();} return x*=f; } int main(){ freopen("bird.in","r",stdin); freopen("bird.out","w",stdout); int p, q, m, n; int fg = 0; scanf("%d%d%d%d", &p, &q, &m, &n); for(int i = 1; i <= n; i++){ a[i] = read(), b[i] = read(), c[i] = read(); if(a[i] >= m && !fg)fg = i; } if(q - p < 2) return !puts("-1"); if(!fg) fg = ++n; if(a[fg] != m){ a[fg] = m, b[fg] = p, c[fg] = q; } int low = 0, high = 0; for(int i = 1; i <= n; i++){ int lf = b[i] + 1, rg = c[i] - 1; low = max(low - (a[i] - a[i - 1]), p + 1); high = min(high + a[i] - a[i - 1], q - 1); if((a[i]&1) != (lf&1))lf++; if((a[i]&1) != (rg&1))rg--; low = max(low, lf); high = min(high, rg); if(rg - lf < 0) return !puts("-1"); if(a[i] == m) return !printf("%d ", (m + low)>>1); } }
第二题:看题应该想到Trie树,但我只想到Trie树求最小异或值(tcl),应该思考一下Trie树的性质;
我们找的时候是贪心走到最低点,其实我们就是想把高位一样的连在一起;所以我们就是把底层的数字相连,形成一个联通块(这个联通块的边权<2^dep),在把这个联通块和另一个联通块相连,是不是就变成了子树合并了;所以我们的Trie树从深往浅合并,每次合并都是从size小的那棵子树中用每个数在另一棵子树中跑Trie树,有点像启发式合并;
每层做O(n)数的查寻,复杂度nloga;有loga层,复杂度 n log^2 a;
#include<bits/stdc++.h> using namespace std; const int M = 200005; const int ME = 5 * 1e6, inf = 2e9; #define ll long long int a[M]; int idc, ch[ME][2], cnt[ME], dep[ME]; ll vmin, ans, bin[55]; void add(int val){ int now = 0; for(int i = 31; i>=0; i--){ int t = bin[i]&val ? 1 : 0; if(!ch[now][t]){ ch[now][t] = ++idc; cnt[idc]++;dep[idc] = i; } now = ch[now][t]; } } void query(int lf, int rg, ll val){ bool fg = 0; if(dep[lf] == 0){ vmin = min(vmin, val); } if(cnt[lf] > cnt[rg])swap(lf, rg); if(ch[lf][0] && ch[rg][0]) query(ch[lf][0], ch[rg][0], val), fg = 1; if(ch[lf][1] && ch[rg][1]) query(ch[lf][1], ch[rg][1], val), fg = 1; if(fg)return ; if(ch[lf][0]) query(ch[lf][0], ch[rg][1], val + bin[dep[lf] - 1]); if(ch[lf][1]) query(ch[lf][1], ch[rg][0], val + bin[dep[lf] - 1]); } void dfs(int now){ if(dep[now] == 0) return ; if(ch[now][0])dfs(ch[now][0]); if(ch[now][1])dfs(ch[now][1]); if(!ch[now][0] || !ch[now][1])return ; vmin = inf; query(ch[now][0], ch[now][1], bin[dep[now]-1]); ans += vmin; } int main(){ freopen("road.in","r",stdin); freopen("road.out","w",stdout); int n; bin[0] = 1; for(int i = 1; i <= 31; i++)bin[i]=bin[i-1]<<1; scanf("%d", &n); for(int i = 1; i <= n; i++){ scanf("%d", &a[i]); add(a[i]); } dep[0] = 32; dfs(0); printf("%lld ", ans); }
第三题;一道巨恶心的大模拟,我题都没看完,不管了,粘标程
#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++ = ‘ ‘, 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 == ‘ ‘) putchar(‘ ‘), 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 : ‘ ‘); r = ‘ ‘, 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; }