平时三测

题解:

第一题:每个柱子可以到达的位置是可求的一个区间,我们得到区间,并和下一个柱子的限制取交集,得到一个新区间,这样一直做下去,就可以得到最终答案的区间,我们肯定贪心走到最低点,知道了这个坐标,就可以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\n", (m + low)>>1);
    }
}
View Code

 

第二题:看题应该想到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\n", ans);
}
View Code

 

 

 

第三题;一道巨恶心的大模拟,我题都没看完,不管了,粘标程

 

#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;
}
View Code

 

转载于:https://www.cnblogs.com/EdSheeran/p/9651482.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值