(有任何问题欢迎留言或私聊 && 欢迎交流讨论哦
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;