Codeforces Round #367 (Div. 2) dp,trie

BB选手,闲的蛋疼写了发C和D,所以只写CD的题解。

C

n个字符串,翻转第i个字符串会有 ci 的代价,问最少代价使所有字符串的字典序单调不减。

dp一发就完了,注意开longlong,INF开大,是单调不减不是单调增

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;
const int SZ = 1000010;
const LL INF = 1e15;

LL val[SZ],dp[SZ][2];

string s1[SZ],s2[SZ];

int main()
{
    int n;
    scanf("%d",&n);
    for(int i = 1;i <= n;i ++)
        scanf("%I64d",&val[i]);
    for(int i = 1;i <= n;i ++)
    {
        cin >> s1[i];
        for(int j = s1[i].length() - 1;j >= 0;j --)
            s2[i] += s1[i][j];
        dp[i][0] = dp[i][1] = INF;
    }
    dp[1][1] = val[1]; dp[1][0] = 0;
    for(int i = 2;i <= n;i ++)
    {
        if(s1[i - 1] <= s1[i])
            dp[i][0] = min(dp[i][0],dp[i - 1][0]);
        if(s2[i - 1] <= s1[i])
            dp[i][0] = min(dp[i][0],dp[i - 1][1]);
        if(s1[i - 1] <= s2[i])
            dp[i][1] = min(dp[i][1],dp[i - 1][0] + val[i]);
        if(s2[i - 1] <= s2[i])
            dp[i][1] = min(dp[i][1],dp[i - 1][1] + val[i]);
    }
//  for(int i = 1;i <= n;i ++)
//      printf("%d %d\n",dp[i][0],dp[i][1]),cout << s1[i] << " " << s2[i] << endl;
    LL ans = min(dp[n][0],dp[n][1]);
    printf("%I64d",ans == INF ? -1 : ans);
    return 0;
}

D

维护一个集合,支持动态加入一个数、删除一个数、从集合中找出一个数使得与给定数异或值最大。

trie裸题,现在div2越来越水了吗……我竟然还调了半天,后来发现输出写错了……

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;

typedef long long LL;
const int SZ = 5000010;
const LL INF = 1e15;

int ch[SZ][2],tot = 1,sz[SZ];

void insert(int x)
{
    int p = 1;
    sz[p] ++;
    for(int i = 31;i >= 0;i --)
    {
        int d = x >> i & 1;
        if(!ch[p][d]) ch[p][d] = ++ tot;
        p = ch[p][d];
        sz[p] ++;
    }
}

void del(int x)
{
    int p = 1;
    sz[p] --;
    for(int i = 31;i >= 0;i --)
    {
        int d = x >> i & 1;
        p = ch[p][d];
        sz[p] --;
    }
}

int ask(int x)
{
    int p = 1,ans = 0;
    for(int i = 31;i >= 0;i --)
    {
        int d = x >> i & 1;
        if(!sz[ch[p][d ^ 1]])
            ans = (ans << 1 | d),p = ch[p][d];
        else 
            ans = (ans << 1 | (d ^ 1)),p = ch[p][d ^ 1];
    }
    return ans ^ x;
}

int main()
{
    int n;
    scanf("%d",&n);
    insert(0);
    for(int i = 1;i <= n;i ++)
    {
        char opt[3]; int x;
        scanf("%s%d",opt,&x);
        if(opt[0] == '+')
            insert(x);
        if(opt[0] == '-')
            del(x);
        if(opt[0] == '?')
            printf("%d\n",ask(x));
    }
    return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值