HDU 1800 Flying to the Mars(Trie字典树 upper_bound)
题意:有一个序列 要组成多个子序列
每个子序列必须单调递增
问最少组成多少个子序列
思路1: 因为严格递增 所以每个数只能在一个子序列中出现一次 出现次数最多的数的次数就是答案
运用 upper_bound(a,a+n,a[i])-lower_bound(a,a+n,a[i]) 求出
(由于数据较水 并没有达到30位)
upper_bound(begin,end,key),start是查找的起点,end是终点,key是关键值,lower_bound()用法一 样,
upper_bound()函数,返回第一个大于要找的值得位置(或者理解是这个元素的下一个位置),
而Lower_bound是小于等于关键字的位 置(或者理解为关键字第一次出现 的位置),
#include<stdio.h> #include<string.h> #include<math.h> #include<iostream> #include<algorithm> #include<queue> #include<stack> #define mem(a,b) memset(a,b,sizeof(a)) #define ll __int64 #define MAXN 1000 #define INF 0x7ffffff #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 using namespace std; int a[5000]; int main() { int i,j,n; while(scanf("%d",&n)!=EOF) { for(i=0; i<n; i++) scanf("%d",&a[i]); sort(a,a+n); int cnt; int maxx=0; for(i=0; i<n; i++) { cnt=(upper_bound(a,a+n,a[i])-lower_bound(a,a+n,a[i])); if(cnt>maxx) maxx=cnt; } printf("%d\n",maxx); } return 0; }
思路2:
当数据达到30位时
就需要运用字典树记录每个数出现的次数
#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> using namespace std; int ch[30000+100][20]; int val[30000+10]; int sz; //节点总数 int idx(char c) {return c-'0';} int ans; void insert(char *s) { int u=0,n=strlen(s); for(int i=0;i<n;i++) { int c=idx(s[i]); if(!ch[u][c]) //节点不存在 { memset(ch[sz],0,sizeof(ch[sz])); ch[u][c]=sz++; //新建节点 } u=ch[u][c];// [上一个数的编号][这个数为c] } val[u]++; //字符串的最后一个字符的附加信息 if(val[u]>ans) ans=val[u]; } int main() { int n,i,j,k; char s[3000+100]; while(scanf("%d",&n)!=EOF) { sz=1; //初始时只有一个根节点 memset(ch[0],0,sizeof(ch[0])); memset(val,0,sizeof(val)); ans=1; for(i=0;i<n;i++) { scanf("%s",s); j=0; while(s[j]=='0') j++; insert(s+j); } printf("%d\n",ans); } return 0; }