Codeforces1084 E. The Fair Nut and Strings(字典树思想)

题意:

有k个长度为n的串,只由字符a和b组成
定义这k个串的权值为不同前缀的总数量,

现在这k个串找不到了,只知道这k个串的字典序>=串S,且<=串T,(S和T的长度也为n),
问原来的k个串的最大权值是多少。

数据范围:n<=5e5,k<=1e9

解法:
假如对所有串建立前缀树(字典树),
那么权值就是节点总数,
现在就是要使得节点总数尽可能大.

那没问题变为给定左右边界,
要求构造一棵字典树,满足叶子不超过k个,
同时节点数尽可能多,输出最多节点数.

那么每层都尽量分二叉,
如果左边界='b',那么有一个节点只能分一叉,-1,
如果右边界='a',那么有一个节点只能分一叉,-1,
如果节点数超过k,那么之后的每层都是k个节点.
code:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define PI pair<int,int>
const int maxm=5e5+5;
const int mod=1e9+7;
char s[maxm];
char t[maxm];
int n,k;
signed main(){
    cin>>n>>k;
    scanf("%s",s+1);
    scanf("%s",t+1);
    int ans=0;
    int temp=1;
    for(int i=1;i<=n;i++){
        temp*=2;//全部分二叉
        if(s[i]=='b')temp--;//左边界='b',那么有一个节点不能二叉.
        if(t[i]=='a')temp--;//右边界='a',那么有一个节点不能二叉.
        if(temp<=k){
            ans+=temp;
        }else{//temp>k,那么后面都是k叉
            ans+=(n-i+1)*k;
            break;
        }
    }
    cout<<ans<<endl;
    return 0;
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值