Gym 101466A: Gaby And Addition 字典树+字典树模板

(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦

Catalog

Problem:Portal传送门

 原题目描述在最下面。
 给你1e6个数字,询问任选两个的和的最大值的最小值。注意:求和不进位。

Solution:

 字典树模板直接上咯。
 每次插入一个数前,询问这个数可以造成的最大和 和 最小和。
 注意把所有数字右对齐弄成相同位数,前面拿0补齐。
 对于数字x当前首位是a,要找最大和,应该优先判断这一层9-a是否存在。对于最小和应该优先判断这一层10-a是否存在。

emmm第一道字典树的题,感觉海星

AC_Code:
#include<bits/stdc++.h>
#define cw T
#define all(x) x.begin(),x.end()
#define mme(a,b) memset((a),(b),sizeof((a))) 
using namespace std;
typedef long long LL;
typedef unsigned long long uLL;
const int N =1e6 + 7;
const int M = 1e6 + 7;
const LL MOD = 1e9 + 7;
const LL INF = 2e18;
const double pi = acos(-1.0);
int n;
struct node{
  int cnt;
  int nxt[11];
  void init(){
    cnt = 0;
    memset(nxt,-1,sizeof(nxt));
  }
}T[N*20];
int le, root;
LL pw[30], mmax, mmin;
void insert(char *s){
  int now = root;
  int slen = 19;
  for(int i = 0;i < slen;i++){
    int x = s[i] - '0';
    if(T[now].nxt[x] == -1){
      T[le].init();
      T[now].nxt[x] = le++; 
    }
    now = T[now].nxt[x];
    T[now].cnt++;
  }
}
LL search_max(char *s){
  int now = root;
  LL ans = 0;
  int slen = 19;
  for(int i = 0, j = slen - 1; i < slen; i++, --j){
    int x = s[i] - '0', flag = 1;
    for(int k = 9 - x; k >= 0; --k){
      if(cw[now].nxt[k]!=-1){
        flag = 0;
        now = T[now].nxt[k];
        ans += ((x+k*1LL)%10)*pw[j];
        break;
      }
    }
    for(int k = 9 ; k > 9 - x && flag; --k){
      if(cw[now].nxt[k]!=-1){
        now = T[now].nxt[k];
        ans += ((x+k*1LL)%10)*pw[j];
        break;
      }
    }
  }
  return ans;
}
LL search_min(char *s){
  int now = root;
  LL ans = 0;
  int slen = 19;
  for(int i = 0, j = slen-1;i < slen; i++, --j){
    int x = s[i] - '0', flag = 1;
    int st = 10 - x;if(st==10)st=0;
    for(int k = st; k <= 9; ++k){
      if(cw[now].nxt[k]!=-1){
        flag = 0;
        now = T[now].nxt[k];
        ans += ((x+k*1LL)%10)*pw[j];
        break;
      }
    }
    for(int k = 0 ; k < st && flag; ++k){
      if(cw[now].nxt[k]!=-1){
        now = T[now].nxt[k];
        ans += ((x+k*1LL)%10)*pw[j];
        break;
      }
    }
  }
  return ans;
}
char ar[N][21];
int main(){
  pw[0]=1;
  for(int i=1;i<=20;++i)pw[i]=pw[i-1]*10;
  scanf("%d", &n);
    root=0;cw[0].init();le=1;
    LL tmp;mmax = 0;mmin=INF;
    for(int i=0;i<n;++i){
      scanf("%lld", &tmp);
      for(int j=18;j>=0;--j){
        ar[i][j]=tmp%10+'0';
        tmp/=10;
      }
      ar[i][20]='\0';
      //printf("* %s %lld\n", ar[i], tmp);
      if(i){
        mmax=max(mmax,search_max(ar[i]));
        mmin=min(mmin,search_min(ar[i]));
      }
      insert(ar[i]);
    }
    /*for(int i=1;i<n;++i){
      mmax=max(mmax,search_max(ar[i]));
      mmin=min(mmin,search_min(ar[i]));
    }*/
    printf("%lld %lld\n", mmin,mmax);

  return 0;
}


字典树模板

struct node{
    int cnt;
    int nex[26];
    void init(){
        cnt = 0;
        memset(nex,-1,sizeof(nex));
    }
}tr[MX];
int le,root;
void insert(char *s){
    int now = root;
    int slen = strlen(s);
    for(int i = 0;i < slen;i++){
        int x = s[i] - 'a';
        if(tr[now].nex[x] == -1){
            tr[le].init();
            tr[now].nex[x] = le++; 
        }
        now = tr[now].nex[x];
        tr[now].cnt++;
    }
}
void Trie_dele(char *s){
  int p = 0;
  int slen = strlen(s);
  for(int i = 0;i < slen;i++){
      int tmp = s[i]-'a';
      p = tr[p].nex[tmp];
      tr[p].cnt--;
  }
}
int search(char *s){
    int now = root;
    int slen = strlen(s);
    for(int i = 0;i < slen;i++){
        int x = s[i] - 'a';
        if(tr[now].nex[x] == -1)
            return 0;
        now = tr[now].nex[x];
    }
    return tr[now].cnt;
}
const int INF = 0x3f3f3f3f;
const LL INFLL = 0x3f3f3f3f3f3f3f3fll;
const int MXM = 1e6 + 7;
typedef pair<int,int> pii;
struct TRIE{
    int nxt[MXM][26], cnt[MXM];
    int root, rear, n;
    int new_node() {
        cnt[++rear] = 0;
        memset(nxt[rear], 0, sizeof(nxt[rear]));
        return rear;
    }
    void init(int _n) {
        rear = 0, n = _n;
        root = new_node();
    }
    void insert(string str) {
        int now = root, tmp;
        for (int i = 0; i < str.size(); i++) {
            tmp = str[i] - 'a';
            if (!nxt[now][tmp]) nxt[now][tmp] = new_node();
            now = nxt[now][tmp];
            cnt[now]++;
        }
    }
    int find(string str) {  //查询str字典序排第几,字符串编号0~n-1
        int now = root, tmp, pos = n - 1;
        for (int i = 0; i < str.size(); i++) {
            tmp = str[i] - 'a';
            for(int j = 25; j > tmp; j--) if (nxt[now][j]) pos -= cnt[nxt[now][j]];
            now = nxt[now][tmp];
        }
        for (int j = 0; j < 26; j++) if (nxt[now][j]) pos -= cnt[nxt[now][j]];
        return pos;
    }
    pii query_pref(string str) { //查询前缀为str的字典序区间
        int l = 0, r = 0, now = root, tmp, pre = n, num;
        for (int i = 0; i < str.size(); i++) {
            tmp = str[i] - 'a';
            if(!nxt[now][tmp])return pii(n + 1,n + 1);//不存在前缀为str的字符串
            num = 0;
            for(int j = tmp; j < 26; j++) if (nxt[now][j]) num += cnt[nxt[now][j]];
            l += pre - num;
            r = l + cnt[nxt[now][tmp]] - 1;
            now = nxt[now][tmp];
            pre = cnt[now];
        }
        return pii(l, r);
    }
}trie;


Problem Description:

这里写图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值