poj 初级训练计划数据结构总结
2016-04-30 00:04
423 查看
两个下午一个晚上搞完了还是学到很多东西的。
poj 1035,3080,1936简单C语言题。3080可以KMP,但数据水可以枚举,KMP的话就是把第一个串的所有子串与下面几个串匹配难度也不大。
poj 2388 就是sort.
poj 2299 求逆序数==归并排序 当两个区间都排好时合并时你就可以跳跃性的直接求一个数和别的数有几个逆序而不是一个一个都比过来。这题可以当归并排序模板。
总体来说哈希容器字典树的运用更熟练了
poj 1611 并查集做的比较裸(路径压缩方法不正确先已知)
poj 3349
每个雪花排个序哈希再排序,第一次处理哈希冲突问题方法太渣
poj 3274
从第一个牛到第n个牛进行累加 记录每个i时的特征累加值也就是1-i(i>=1&&i<=n)时各个特征累加值。再以第一个特征值为基准求出每个s的各个特征的递增趋势。
当i跟j特征的递增趋势一样时那【i+1,j】这个区间个特征值相等。因为一个曲线每个点都往上平移一段相等长度时导数是不变的。
递增趋势是要哈希优化的(把n^2优化成n)
poj 1840 普通哈希
poj 2002 几何+哈希
1.把每个点的x和y轴坐标哈希
2.哈希处理冲突用邻接表比用链表更好快一倍
3.两个点(x1,y1),(x2,y2) 设x = x2-x1,y = y2-y1,则另外两个能够与这两个点组成正方形的点为(x1+y,y1-x)(x2+y,y2-x)或(x1-y,y1+x)(x2-y,y2+x);
poj 2503 map(红黑树哈希)
poj 3253 哈夫曼+堆优化可以但我用的set
poj 2422
用堆维护n个最小值 o(n*n*logn) 不用的话直接枚举n个最小值o(n*n*n);
poj 1442 堆优化
建两个堆 一个维护最小值(后几个大值的最小值)一个维护最大值(前几个最大值的最小值)
poj 2513
1.字典树哈希 把每个单词都给个编号。
2.求欧拉路
(1)判断连通,并查集这题的路径压缩是正确的。
(2)每个点的度必须都为偶数或有两个是奇数,记录边数就行
poj 2418 裸字典树 注意不止大小字母太坑
poj 1035,3080,1936简单C语言题。3080可以KMP,但数据水可以枚举,KMP的话就是把第一个串的所有子串与下面几个串匹配难度也不大。
poj 2388 就是sort.
poj 2299 求逆序数==归并排序 当两个区间都排好时合并时你就可以跳跃性的直接求一个数和别的数有几个逆序而不是一个一个都比过来。这题可以当归并排序模板。
总体来说哈希容器字典树的运用更熟练了
#include<cstdio> int a[600000],temp[600000],n; long long sum;//结果可能很大 void mergeArray(int l,int r)//归并 { int lStart = l,lEnd = (l+r)/2, rStart = (l+r)/2+1,rEnd = r, i1 = 0; while(lStart<=lEnd&&rStart<=rEnd) { if(a[lStart]<=a[rStart]) { temp[i1] = a[lStart]; lStart++; i1++; } else { sum+=(long long)(lEnd-lStart+1);//求逆序数 temp[i1] = a[rStart]; rStart++; i1++; } } for(int i=lStart;i<=lEnd;i++) { temp[i1] = a[i]; i1++; } for(int i=rStart;i<=rEnd;i++) { temp[i1] = a[i]; i1++; } for(int i=l;i<=r;i++) a[i] = temp[i-l]; } void mergeSort(int l,int r)//二分 { if(l<r) { mergeSort(l,(r+l)/2); mergeSort((r+l)/2+1,r); mergeArray(l,r); } } int main() { while(scanf("%d",&n)&&n) { sum = 0; for(int i=0;i<n;i++) scanf("%d",&a[i]); mergeSort(0,n-1); printf("%I64d\n",sum); } return 0; }
poj 1611 并查集做的比较裸(路径压缩方法不正确先已知)
#include<cstdio> #include<algorithm> int n,m,l,fa[30005],am[30005],faGroup[30005]; void init() { for(int i=0;i<n;i++) { fa[i] = i; am[i] = 1; } } int toGetFarther(int x) { while(fa[x]!=x) x = fa[x]; return x; } void unon() { int maam = -1,max = -1; scanf("%d",&l); for(int i=0;i<l;i++) { int s; scanf("%d",&s); faGroup[i] = toGetFarther(s); } for(int i=0;i<l;i++) if(am[faGroup[i]]>maam){ maam = am[faGroup[i]]; max = faGroup[i]; } for(int i=0;i<l;i++) { if(faGroup[i]!=max){ fa[faGroup[i]]= max; am[max]+=am[faGroup[i]]; } } } int main() { while(scanf("%d%d",&n,&m)!=EOF) { if(n+m==0)break; init(); while(m--) { unon(); } int ans = 1,re = toGetFarther(0); for(int i=1;i<n;i++) if(re==toGetFarther(i))ans++; printf("%d\n",ans); } return 0; }
poj 3349
每个雪花排个序哈希再排序,第一次处理哈希冲突问题方法太渣
#include<cstdio> #include<algorithm> #define ll long long #define mod 2071723427 using namespace std; struct node{ int am,ele[6]; }a[110000]; int n,w[6]; bool cmp(node no1,node no2) { return no1.am<no2.am; } int main() { while(scanf("%d",&n)!=EOF) { for(int i=0;i<n;i++) { for(int j=0;j<6;j++) scanf("%d",&w[j]); sort(w,w+6); for(int j=0;j<6;j++) a[i].ele[j] = w[j]; a[i].am = 0; for(int j=0;j<6;j++) a[i].am = (a[i].am*10000777+a[i].ele[j])%mod; } sort(a,a+n,cmp); bool sym =false; for(int i=1;i<n;i++) if(a[i].am==a[i-1].am) { int sum = 0; for(int j=0;j<6;j++) if(a[i].ele[j]==a[i-1].ele[j])sum++; if(sum==6) { sym = true; break; } } if(!sym)printf("No two snowflakes are alike.\n"); else printf("Twin snowflakes found.\n"); } return 0; }
poj 3274
从第一个牛到第n个牛进行累加 记录每个i时的特征累加值也就是1-i(i>=1&&i<=n)时各个特征累加值。再以第一个特征值为基准求出每个s的各个特征的递增趋势。
当i跟j特征的递增趋势一样时那【i+1,j】这个区间个特征值相等。因为一个曲线每个点都往上平移一段相等长度时导数是不变的。
递增趋势是要哈希优化的(把n^2优化成n)
#include<cstdio> #include<cstring> #include<algorithm> #define mod 197377 using namespace std; int hash[200000][20],len[200000],n,k; int a[110000][34]; int main() { while(scanf("%d%d",&n,&k)!=EOF) { int ans; scanf("%d",&ans); memset(len,0,sizeof(len)); for(int i=0;i<k;i++) a[1][i] = (ans&(1<<i))/(1<<i); for(int i=2;i<=n;i++) { scanf("%d",&ans); for(int j=0;j<k;j++) a[i][j] = a[i-1][j]+(ans&(1<<j))/(1<<j); int w = a[i-1][0]; for(int j=0;j<k;j++) a[i-1][j]-=w; } int w = a [0]; for(int j=0;j<k;j++) a [j]-=w; ans = 0; len[0] = 1; for(int i=1;i<=n;i++) { int pre = 0; for(int j=0;j<k;j++) pre = (pre*30+a[i][j]+mod)%mod; for(int j=0;j<len[pre];j++) { int sum = 0; for(int k1=0;k1<k;k1++) if(a[hash[pre][j]][k1]==a[i][k1])sum++; else break; if(sum==k) { ans = max(ans,i-hash[pre][j]); break; } } hash[pre][len[pre]] = i; len[pre]++; } printf("%d\n",ans); } return 0; }
poj 1840 普通哈希
#include<cstdio> #include<cstring> #include<algorithm> #define mod 12500000 using namespace std; short mp[25000005]; int a,b,c,d,e,sum,am[105]; int main() { int i1 = 0; for(int i=1;i<=50;i++) { am[i1] = i*i*i; i1++; am[i1] = -1*(i*i*i); i1++; } while(scanf("%d%d%d%d%d",&a,&b,&c,&d,&e)!=EOF) { sum = 0; memset(mp,0,sizeof(mp)); for(int i=0;i<i1;i++) for(int j=0;j<i1;j++) mp[am[i]*a+am[j]*b+mod]++; for(int i=0;i<i1;i++) for(int j=0;j<i1;j++) for(int k=0;k<i1;k++) if((am[i]*d+am[j]*e+am[k]*c)>=-12500000&&(am[i]*d+am[j]*e+am[k]*c)<=12500000) sum+=mp[mod-1*(am[i]*d+am[j]*e+am[k]*c)]; printf("%d\n",sum); } return 0; }
poj 2002 几何+哈希
1.把每个点的x和y轴坐标哈希
2.哈希处理冲突用邻接表比用链表更好快一倍
3.两个点(x1,y1),(x2,y2) 设x = x2-x1,y = y2-y1,则另外两个能够与这两个点组成正方形的点为(x1+y,y1-x)(x2+y,y2-x)或(x1-y,y1+x)(x2-y,y2+x);
#include<cstdio> #include<cstring> #define mul 27 #define mod 5013 int sum,n,l,x,y; struct node{ int x,y; }node[5025]; int next[5025],last[5025]; bool judge(int va,int x,int y) { int pre = last[va]; for(;pre!=-1;pre = next[pre]) if(node[pre].x==x&&node[pre].y==y)return true; return false; } int main() { while(scanf("%d",&n)&&n) { sum = 0; memset(next,-1,sizeof(next)); memset(last,-1,sizeof(last)); for(int i=0;i<n;i++) { scanf("%d%d",&x,&y); int pre = ((x*mul+y)%mod+mod)%mod; node[i].x = x; node[i].y = y; next[i] = last[pre]; last[pre] = i; } for(int i=0;i<n;i++) for(int j=i+1;j<n;j++) { int x3,y3,x4,y4,x = node[i].x-node[j].x,y = node[i].y-node[j].y; x3 = node[i].x+y,y3 = node[i].y-x; x4 = node[j].x+y,y4 = node[j].y-x; if(judge(((x3*mul+y3)%mod+mod)%mod,x3,y3)&&judge(((x4*mul+y4)%mod+mod)%mod,x4,y4))sum++; x3 = node[i].x-y,y3 = node[i].y+x; x4 = node[j].x-y,y4 = node[j].y+x; if(judge(((x3*mul+y3)%mod+mod)%mod,x3,y3)&&judge(((x4*mul+y4)%mod+mod)%mod,x4,y4))sum++; } printf("%d\n",sum/4); } return 0; }
poj 2503 map(红黑树哈希)
#include<cstdio> #include<string> #include<string.h> #include<iostream> #include<map> using namespace std; string a,b; char str[30]; int main() { map<string,string>mp; while(gets(str)&&str[0]!='\0') { int pre = 0; a = b ="\0"; while(str[pre]!=' ') pre++; str[pre] = '\0'; a += str; b += str+pre+1; mp[b] = a; } while(cin>>a) { string b = mp[a]; if(b[0]!='\0')cout<<b<<endl; else cout<<"eh"<<endl; } return 0; }
poj 3253 哈夫曼+堆优化可以但我用的set
#include<cstdio> #include<set> #define ll long long using namespace std; int n; int main() { scanf("%d",&n); { ll sum = 0; multiset<ll>s; for(int i=0;i<n;i++) { ll pre; scanf("%I64d",&pre); s.insert(pre); } for(int i=0;i<n-1;i++) { int pre = *s.begin(); s.erase(s.lower_bound(pre)); int pre2 = *s.begin(); s.erase(s.lower_bound(pre2)); sum+=(pre+pre2); s.insert(pre+pre2); } s.clear(); printf("%I64d\n",sum); } return 0; }
poj 2422
用堆维护n个最小值 o(n*n*logn) 不用的话直接枚举n个最小值o(n*n*n);
#include<cstdio> #include<algorithm> using namespace std; int ans[2005],n,m,pre[2005],t,sum[2005]; int main() { scanf("%d",&t); while(t--) { scanf("%d%d",&m,&n); for(int i=0;i<n;i++) scanf("%d",&ans[i]); m--; while(m--) { sort(ans,ans+n); for(int i=0;i<n;i++) scanf("%d",&pre[i]); sort(pre,pre+n); for(int i=0;i<n;i++) sum[i] = ans[i]+pre[0]; make_heap(sum,sum+n); for(int i=1;i<n;i++) for(int j=0;j<n;j++) { int temp = ans[j]+pre[i]; if(temp>=sum[0])break; pop_heap(sum,sum+n); sum[n-1] = temp; push_heap(sum,sum+n); } for(int i=0;i<n;i++) ans[i] = sum[i]; } sort(ans,ans+n); for(int i=0;i<n-1;i++) printf("%d ",ans[i]); printf("%d\n",ans[n-1]); } return 0; }
poj 1442 堆优化
建两个堆 一个维护最小值(后几个大值的最小值)一个维护最大值(前几个最大值的最小值)
#include<cstdio> #include<algorithm> using namespace std; int va[40000],heapMin[40000],heapMax[40000],n,m,lMin,lMax,k; bool cmp(int a,int b) { return a>b; } int main() { while(scanf("%d%d",&n,&m)!=EOF) { lMin = 0; lMax = 0; int all = 0; for(int i=0;i<n;i++) scanf("%d",&va[i]); for(int i=0;i<m;i++) { int pre; scanf("%d",&pre); while(all<pre) { heapMin[lMin] = va[all]; all++; lMin++; push_heap(heapMin,heapMin+lMin,cmp); if(lMax&&heapMin[0]<heapMax[0]) { pop_heap(heapMin,heapMin+lMin,cmp); pop_heap(heapMax,heapMax+lMax); int t = heapMin[lMin-1]; heapMin[lMin-1] = heapMax[lMax-1]; heapMax[lMax-1] = t; push_heap(heapMin,heapMin+lMin,cmp); push_heap(heapMax,heapMax+lMax); } } printf("%d\n",heapMin[0]); heapMax[lMax] = heapMin[0]; lMax++; push_heap(heapMax,heapMax+lMax); pop_heap(heapMin,heapMin+lMin,cmp); lMin--; } } return 0; }
poj 2513
1.字典树哈希 把每个单词都给个编号。
2.求欧拉路
(1)判断连通,并查集这题的路径压缩是正确的。
(2)每个点的度必须都为偶数或有两个是奇数,记录边数就行
#include<cstdio> #include<string> #include<iostream> #include<cstring> using namespace std; int all[50005],pre = 0,fa[500005],ans[2],root[50005],id = 0; string a,b; class trieNode{ public: int id; trieNode *next[28]; trieNode() { id = -1; memset(next,0,sizeof(next)); } }*Root = new trieNode; int insertTree(string a) { int l = a.size(); trieNode *p = Root; for(int i=0;i<l;i++) if(p->next[a[i]-'a']!=NULL) p = p->next[a[i]-'a']; else{ trieNode *q = new trieNode; p->next[a[i]-'a'] = q; p = q; } if(p->id!=-1)return p->id; else { p->id = id; id++; return id-1; } } void init() { for(int i=0;i<=500001;i++)fa[i] = i; } int getFarther(int i) { if(i!=fa[i])fa[i] = getFarther(fa[i]); return fa[i]; } void unionFind(int x,int y) { int faX = getFarther(x); int faY = getFarther(y); fa[faY] = faX; } int main() { bool sym = false; init(); int i1 = 0; while(cin>>a>>b) { int x = insertTree(a); int y = insertTree(b); //printf("%d %d\n",x,y); unionFind(x,y); all[x]++; all[y]++; i1++; } for(int i=0;i<id;i++) { int j = i; while(fa[j]!=j)j = fa[j]; root[j]++; if(root[j]==id)sym = true; } if(sym) { for(int i=0;i<id;i++) ans[all[i]%2]++; if(!(ans[1]==2||ans[1]==0))sym = false; } if(sym||i1==0)printf("Possible\n"); else printf("Impossible\n"); return 0; }
poj 2418 裸字典树 注意不止大小字母太坑
#include<cstdio> #include<cstring> char s[50]; int sum = 0; class trieNode{ public: int sum; trieNode *next[130]; trieNode() { memset(next,0,sizeof(next)); sum = 0; } }*root = new trieNode; void insertTrie(char s[]) { trieNode *p = root; int l = strlen(s); for(int i=0;i<l;i++) { // printf("%d %c\n",i,s[i]); if(p->next[s[i]]==NULL) { trieNode *q = new trieNode; p->next[s[i]] = q; p = p->next[s[i]]; } else p = p->next[s[i]]; } (p->sum)++; } void dfs(trieNode *p,char s[],int l) { if(p->sum){ s[l] = '\0'; printf("%s %.4f\n",s,(double)(p->sum)/sum*100.0); } for(int i=0;i<=129;i++) { if(p->next[i]!=NULL) { //printf("%c\n",i); s[l] = i; dfs(p->next[i],s,l+1); } } } int main() { sum = 0; while(gets(s)!=NULL) { sum++; insertTrie(s); } if(sum==0)return 0; dfs(root,s,0); return 0; }
相关文章推荐
- 一、hbase的核心数据结构
- 数据结构与算法分析(1)引论
- C语言数据结构学习网站
- hdu 4193(单调队列)
- 快速排序
- delphi.数据结构.链表
- 集合框架(用LinkedList模拟栈数据结构的集合并测试案例)
- 数据结构排序算法之归并排序
- 冒泡排序
- 希尔排序
- 数据结构之字符串ADT
- 数据结构与算法——有向无环图的拓扑排序C++实现
- 排序算法性能比较练习——《数据结构、算法与应用》
- 基本数据结构
- 数据结构------绪论
- 关于程序运行时的数据结构
- 学JS必看-JavaScript数据结构深度剖析
- 数据结构和算法 – 3.堆栈和队列
- 数据结构算法——单链表
- 【数据结构与算法】寻找最大的K个数