hihoCoder太阁最新面经算法竞赛2
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hihoCoder太阁最新面经算法竞赛2相关的知识,希望对你有一定的参考价值。
A 任务分配
描述
给定 N 项任务的起至时间( S1, E1 ), ( S2, E2 ), ..., ( SN, EN ), 计算最少需要多少台机器才能按时完成所有任务。
同一时间一台机器上最多进行一项任务,并且一项任务必须从头到尾保持在一台机器上进行。任务切换不需要时间。
输入
第一行一个整数 N,(1 ≤ N ≤ 100000),表示任务的数目。 以下 N 行每行两个整数 Si, Ei,(0 ≤ Si < Ei ≤ 1000000000),表示任务的起至时间。
输出
输出一个整数,表示最少的机器数目。
题解:线段树(区间更新,离散化)
代码:
1 /*任务分配*/ 2 #include<cstdio> 3 #include<algorithm> 4 #include<map> 5 using namespace std; 6 7 const int maxn=2*1e5+10; 8 9 struct data{ 10 int s,e; 11 int ss,ee; 12 }; 13 struct data line[maxn]; 14 int point[maxn*2]; 15 int tree[maxn*4]; 16 int temp[maxn*4]; 17 18 int max(int a,int b) 19 { 20 return a<b?b:a; 21 } 22 23 void Build(int l,int r,int n) 24 { 25 if(l==r) 26 { 27 tree[n]=0; 28 temp[n]=0; 29 return; 30 } 31 int mid=(l+r)/2; 32 Build(l,mid,n*2); 33 Build(mid+1,r,n*2+1); 34 tree[n]=max(tree[n*2],tree[n*2+1]); 35 } 36 void Updata(int l,int r,int p,int q,int n) 37 { 38 if(p<=l&&r<=q) 39 { 40 tree[n]++; 41 temp[n]+=1; 42 return; 43 } 44 if(temp[n]) 45 { 46 temp[n*2]+=temp[n];temp[n*2+1]+=temp[n]; 47 tree[n*2]+=temp[n];tree[n*2+1]+=temp[n]; 48 temp[n]=0; 49 } 50 int mid=(l+r)/2; 51 if(p<=mid) Updata(l,mid,p,q,n*2); 52 if(q>mid) Updata(mid+1,r,p,q,n*2+1); 53 tree[n]=max(tree[n*2],tree[n*2+1]); 54 } 55 int main() 56 { 57 int N; 58 while(scanf("%d",&N)!=EOF) 59 { 60 61 for(int i=0;i<N;i++) 62 { 63 scanf("%d%d",&line[i].s,&line[i].e); 64 point[i*2]=line[i].s;point[i*2+1]=line[i].e; 65 } 66 sort(point,point+2*N); 67 map<int,int> a; 68 a[point[1]]=0; 69 for(int i=0;i<2*N;i++) 70 { 71 if(point[i]>point[i-1]) 72 a[point[i]]=a[point[i-1]]+1; 73 else 74 a[point[i]]=a[point[i-1]]; 75 } 76 for(int i=0;i<N;i++) 77 { 78 line[i].ss=a[line[i].s]; 79 line[i].ee=a[line[i].e]; 80 } 81 82 //for(int i=0;i<N;i++) 83 // printf("%d %d %d %d\\n",line[i].s,line[i].ss,line[i].e,line[i].ee); 84 85 Build(1,maxn,1); 86 for(int i=0;i<N;i++) 87 { 88 Updata(1,maxn,line[i].ss+1,line[i].ee,1); 89 } 90 printf("%d\\n",tree[1]); 91 } 92 return 0; 93 94 }
B 岛屿
描述
给你一张某一海域卫星照片,你需要统计:
1. 照片中海岛的数目
2. 照片中面积不同的海岛数目
3. 照片中形状不同的海盗数目
其中海域的照片如下,"."表示海洋,"#"表示陆地。在"上下左右"四个方向上连在一起的一片陆地组成一座岛屿。
.####.. .....#. ####.#. .....#. ..##.#.
上图所示的照片中一共有4座岛屿;其中3座面积为4,一座面积为2,所以不同面积的岛屿数目是2;有两座形状都是"####",所以形状不同的岛屿数目为3。
输入
第一行包含两个人整数:N 和 M,(1 ≤ N, M ≤ 50),表示照片的行数和列数。
以下一个 N * M 的矩阵,表示表示海域的照片。
输出
输出3个整数,依次是照片中海岛的数目、面积不同的海岛数目和形状不同的海岛数目。
样例输入
5 7 .####.. .....#. ####.#. .....#. ..##.#.
样例输出
4 2 3
题解:BFS求联通块得出海岛的数目。在搜索时记录下海岛大小,放入map,最后得出面积不同的海岛数目。在搜索时将个海岛放入一个数组,这个数组记录了组成这个海岛所有#的位置,然后将这个数组排序。判断海岛是否相同,只要看其中#的个数是否相等,再看每个#相对第一个#的位置是否相同。
代码:
1 /*岛屿*/ 2 #include<cstdio> 3 #include<cstring> 4 #include<map> 5 #include<algorithm> 6 #include<cmath> 7 #include<queue> 8 using namespace std; 9 10 const int maxn=60; 11 12 int N,M; 13 char land[maxn][maxn]; 14 int vis[maxn][maxn]; 15 int dx[4]={-1,1,0,0},dy[4]={0,0,-1,1}; 16 int ans1,ans2,ans3; 17 map<int,int> a; 18 19 struct data{ 20 int x,y; 21 int num; 22 int has; 23 }; 24 struct data all[3000][3000]; 25 26 27 bool cmp2(struct data c,struct data d) 28 { 29 if(c.x!=d.x) 30 return c.x<d.x; 31 else 32 return c.y<d.y; 33 } 34 35 int same(struct data c[],struct data d[]) 36 { 37 int len=c[0].num; 38 if(len==1) return 1; 39 int flag=1; 40 for(int i=2;i<=len;i++) 41 { 42 if(((c[i].x-c[i-1].x)==(d[i].x-d[i-1].x))&&((c[i].y-c[i-1].y)==(d[i].y-d[i-1].y))) 43 continue; 44 else 45 { 46 flag=0; 47 break; 48 } 49 } 50 return flag; 51 } 52 void BFS(int x,int y) 53 { 54 vis[x][y]=1; 55 queue<struct data> Q; 56 struct data first,next; 57 first.x=x;first.y=y; 58 Q.push(first); 59 all[ans1][0].num=0; 60 while(!Q.empty()) 61 { 62 first=Q.front();Q.pop(); 63 all[ans1][all[ans1][0].num+1].x=first.x;all[ans1][all[ans1][0].num+1].y=first.y; 64 all[ans1][0].num++; 65 for(int i=0;i<4;i++) 66 { 67 next.x=first.x+dx[i];next.y=first.y+dy[i]; 68 if(next.x<0||next.x>=N||next.y<0||next.y>=M) 69 continue; 70 if(vis[next.x][next.y]==1) 71 continue; 72 if(land[next.x][next.y]==‘.‘) 73 continue; 74 75 Q.push(next); 76 vis[next.x][next.y]=1; 77 } 78 } 79 a[all[ans1][0].num]++; 80 } 81 82 int main() 83 { 84 while(scanf("%d%d",&N,&M)!=EOF) 85 { 86 memset(land,0,sizeof(land)); 87 for(int i=0;i<N;i++) 88 scanf("%s",land[i]); 89 memset(vis,0,sizeof(vis)); 90 ans1=0;ans2=0;ans3=0; 91 a.clear(); 92 for(int i=0;i<N;i++) 93 { 94 for(int j=0;j<M;j++) 95 { 96 if(land[i][j]==‘#‘&&vis[i][j]==0) 97 { 98 BFS(i,j); 99 ans1++; 100 } 101 } 102 } 103 ans2=a.size(); 104 for(int i=0;i<ans1;i++) 105 sort(all[i],all[i]+all[i][0].num,cmp2); 106 for(int i=0;i<3000;i++) 107 all[i][0].has=0; 108 for(int i=0;i<ans1;i++) 109 { 110 if(all[i][0].has==1) 111 continue; 112 for(int j=i+1;j<ans1;j++) 113 { 114 if(all[j][0].has==0&&(all[i][0].num==all[j][0].num)&&same(all[i],all[j])) 115 { 116 ans3++; 117 all[j][0].has=1; 118 } 119 } 120 all[i][0].has=1; 121 } 122 printf("%d %d %d\\n",ans1,ans2,ans1-ans3); 123 } 124 return 0; 125 }
C 二进制小数
描述
给定一个十进制小数X,判断X的二进制表示是否是有限确定的。
例如0.5的二进制表示是0.1,0.75的二进制表示是0.11,0.3没有确定有限的二进制表示。
输入
第一行包含一个整数 T (1 ≤ T ≤ 10),表示测试数据的组数。
以下T行每行包含一个十进制小数 X (0 < X < 1)。 X一定是以"0."开头,小数部分不超过100位。
输出
对于每组输入,输出 X 的二进制表示或者NO(如果 X 没有确定有限的二进制表示)。
样例输入
3 0.5 0.75 0.3
样例输出
0.1 0.11 NO
题解:小数第二级制就是将小数乘2,得到整数部分,再取小数部分进行操作。那么什么时候这个小数无法用有限位的二进制表示呢?可以知道,要结束乘2的操作,那么肯定要小数部分为0。我们观察最后小数的最后一位,我们对小数不断乘2,最后一位也乘2,如果这个数在乘2后可以变成0,那么小数部分就可以缩短,直至全部为0。很容易知道,只有5可以在乘2之后得到0,其他数字都是不可以的。所以我们只需要不断模拟操作,同时检查小数最后一个数字是不是5。
代码:
1 /*二进制小数*/ 2 #include<cstdio> 3 #include<map> 4 #include<cstring> 5 using namespace std; 6 7 int ans[100000]; 8 int s[150]; 9 int rear; 10 int flag=1; 11 12 int muti() 13 { 14 for(int i=2;i<=rear;i++) 15 s[i]*=2; 16 for(int i=rear;i>=2;i--) 17 { 18 if(s[i]>=10) 19 { 20 s[i-1]++; 21 s[i]%=10; 22 } 23 } 24 for(rear=140;rear>=1;rear--) 25 { 26 if(s[rear]==0) continue; 27 else break; 28 } 29 if(rear!=1&&s[rear]!=5) 30 flag=0; 31 } 32 33 34 int main() 35 { 36 int T; 37 scanf("%d",&T); 38 while(T--) 39 { 40 char S[150]; 41 memset(S,0,sizeof(S)); 42 scanf("%s",S); 43 memset(s,0,sizeof(s)); 44 int len=strlen(S); 45 for(int i=2;i<len;i++) 46 s[i]=S[i]-‘0‘; 47 memset(ans,0,sizeof(ans)); 48 len=1; 49 flag=1; 50 rear=strlen(S)-1; 51 while(1) 52 { 53 muti(); 54 if(flag==0) break; 55 ans[len++]=s[1]; 56 s[1]=0; 57 if(rear==1) break; 58 } 59 if(flag==0) 60 printf("NO\\n"); 61 else 62 { 63 printf("0."); 64 for(int i=1;i<len;i++) 65 printf("%d",ans[i]); 66 printf("\\n"); 67 } 68 memset(S,0,sizeof(S)); 69 } 70 return 0; 71 }
以上是关于hihoCoder太阁最新面经算法竞赛2的主要内容,如果未能解决你的问题,请参考以下文章