[关闭]
@iamtts 2017-04-22T14:28:39.000000Z 字数 4245 阅读 923

第二学期第二次训练

A - Binary Simulation

题目大意:给一串二进制数,现在有两种指令:

1.I a b 转换a位到b位的数字(0-1,1-0)
2. Q a 查询第a位数字

解题思路:使用树状数组记录转换次数,询问时根据转换次数决定0还是1

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <iostream>
  4. #include <algorithm>
  5. using namespace std;
  6. int bit[100005],n;
  7. char raw[100005];
  8. int lowbit(int x)
  9. {
  10. return x&(-x);
  11. }
  12. void add(int p,int x)
  13. {
  14. while (p<=n)
  15. {
  16. bit[p]+=x;
  17. p+=lowbit(p);
  18. }
  19. }
  20. int sum(int p)
  21. {
  22. int s=0;
  23. while (p)
  24. {
  25. s+=bit[p];
  26. p-=lowbit(p);
  27. }
  28. return s;
  29. }
  30. int main()
  31. {
  32. int t,Case=0;
  33. scanf("%d",&t);
  34. while (t--)
  35. {
  36. memset(bit,0,sizeof(bit));
  37. scanf("%s",raw);
  38. n=strlen(raw);
  39. int tt;
  40. scanf("%d",&tt);
  41. printf("Case %d:\n",++Case);
  42. while(tt--)
  43. {
  44. char ch;
  45. getchar();
  46. scanf("%c",&ch);
  47. if (ch=='I')
  48. {
  49. int a,b;
  50. scanf(" %d %d",&a,&b);
  51. add(a,1);
  52. add(b+1,-1);
  53. }
  54. else
  55. {
  56. int a;
  57. scanf(" %d",&a);
  58. printf("%d\n",sum(a)%2?1^(raw[a-1]-'0'):(raw[a-1]-'0'));
  59. }
  60. }
  61. }
  62. return 0;
  63. }

B - Points in Segments

题目大意:给定一串数,按从小到大的标号排好,现有q组询问形如:a,b,表示询问a~b的闭区间内有多少数

解题思路:因为输入数字递增,可以用二分法查找a和b的位置,然后相减

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <vector>
  7. #define pi acos(0.0)*2
  8. #define maxn 100005
  9. #define INF 1<<30
  10. using namespace std;
  11. int n,q;
  12. int a[100005];
  13. int main()
  14. {
  15. int t,Case=0;
  16. scanf("%d",&t);
  17. while (t--)
  18. {
  19. scanf("%d%d",&n,&q);
  20. printf("Case %d:\n",++Case);
  21. for (int i=0;i<n;i++) scanf("%d",&a[i]);
  22. while (q--)
  23. {
  24. int x,y;
  25. scanf("%d%d",&x,&y);
  26. int ans=upper_bound(a,a+n,y)-lower_bound(a,a+n,x);
  27. printf("%d\n",ans);
  28. }
  29. }
  30. return 0;
  31. }

C - Calm Down

题目大意:给出一个圆的半径,在园内部沿着圆周填充n个小圆,使之恰好铺满圆周

解题思路:简单数学题

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <iostream>
  5. #include <algorithm>
  6. #define pi acos(0.0)*2
  7. using namespace std;
  8. int main()
  9. {
  10. int t,Case=0;
  11. scanf("%d",&t);
  12. while (t--)
  13. {
  14. double R,n,r;
  15. scanf("%lf%lf",&R,&n);
  16. double a=sin(pi/n);
  17. r=R*a/(1+a);
  18. printf("Case %d: %lf\n",++Case,r);
  19. }
  20. return 0;
  21. }

D - Neighbor House

题目大意:有n个房子排成一列,每个房子有三种颜色来粉刷,各有不同的代价,相邻两个房子不能同色,求最少费用

解题思路:dp,状态转移方程:

dp[i][0]=min(dp[i-1][1]+a[i-1][0],dp[i-1][2]+a[i-1][0])
dp[i][1]=min(dp[i-1][0]+a[i-1][1],dp[i-1][2]+a[i-1][1])
dp[i][2]=min(dp[i-1][0]+a[i-1][2],dp[i-1][1]+a[i-1][2])
0,1,2代表不同颜色

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <iostream>
  5. #include <algorithm>
  6. #define pi acos(0.0)*2
  7. #define maxn 100005
  8. #define INF 1<<30
  9. using namespace std;
  10. int a[20][3],n,dp[21][3];
  11. int ans;
  12. int main()
  13. {
  14. int t,Case=0;
  15. scanf("%d",&t);
  16. while (t--)
  17. {
  18. ans=INF;
  19. scanf("%d",&n);
  20. for (int i=0;i<n;i++)
  21. {
  22. for (int j=0;j<3;j++)
  23. scanf("%d",&a[i][j]);
  24. }
  25. for (int i=1;i<=n;i++)
  26. {
  27. dp[i][1]=min(dp[i-1][0]+a[i-1][1],dp[i-1][2]+a[i-1][1]);
  28. dp[i][0]=min(dp[i-1][1]+a[i-1][0],dp[i-1][2]+a[i-1][0]);
  29. dp[i][2]=min(dp[i-1][0]+a[i-1][2],dp[i-1][1]+a[i-1][2]);
  30. }
  31. printf("Case %d: %d\n",++Case,min(dp[n][2],min(dp[n][1],dp[n][0])));
  32. }
  33. return 0;
  34. }

E - Array Queries

题目大意:给定n个数字,有询问形如:a,b,询问a~b全闭区间内的最小值

解题思路:线段树,每个节点(除了叶子节点)储存区间内最小值,注意空间开4倍,血的教训。

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <iostream>
  5. #include <algorithm>
  6. #define pi acos(0.0)*2
  7. #define maxn 100005
  8. #define INF 100005
  9. using namespace std;
  10. int n,dat[4*maxn];
  11. void init(int n_)
  12. {
  13. n=1;
  14. while (n<n_) n*=2;
  15. for (int i=0;i<2*n-1;i++) dat[i]=INF;
  16. }
  17. void update(int k,int a)
  18. {
  19. k=n-1+k;
  20. dat[k]=a;
  21. while (k)
  22. {
  23. k=(k-1)/2;
  24. dat[k]=min(dat[k*2+1],dat[k*2+2]);
  25. }
  26. }
  27. int query(int a,int b,int k,int l,int r)
  28. {
  29. if (r<a || l>b) return INF;
  30. if (a<=l && r<=b) return dat[k];
  31. else
  32. {
  33. int vl=query(a,b,2*k+1,l,(l+r)/2);
  34. int vr=query(a,b,2*k+2,(l+r)/2+1,r);
  35. return min(vl,vr);
  36. }
  37. }
  38. int main()
  39. {
  40. int t,Case=0;
  41. scanf("%d",&t);
  42. while (t--)
  43. {
  44. int nn,q;
  45. scanf("%d%d",&nn,&q);
  46. init(nn);
  47. printf("Case %d:\n",++Case);
  48. for (int i=0;i<nn;i++)
  49. {
  50. int x;
  51. scanf("%d",&x);
  52. update(i,x);
  53. }
  54. for (int i=0;i<q;i++)
  55. {
  56. int a,b;
  57. scanf("%d%d",&a,&b);
  58. printf("%d\n",query(a-1,b-1,0,0,n-1));
  59. }
  60. }
  61. return 0;
  62. }

F - Farthest Nodes in a Tree

题目大意:给定一棵树,求最远的两个节点间的距离

解题思路:两次bfs,第一次从随机一个点开始,寻找最远的点,并记录,第二次从那个最远的点寻找距离自己最远的点,这两点的距离就是树的直径,证明略去。

AC代码:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <cmath>
  4. #include <iostream>
  5. #include <algorithm>
  6. #include <vector>
  7. #define pi acos(0.0)*2
  8. #define maxn 100005
  9. #define INF 1<<30
  10. using namespace std;
  11. struct node
  12. {
  13. int to,cost;
  14. node(int x,int y):to(x),cost(y){}
  15. };
  16. vector<node> G[30005];
  17. int n,pos_1,pos_2,dis;
  18. bool vis[30005];
  19. void dfs(int u,int d)
  20. {
  21. vis[u]=1;
  22. if (d>dis) {dis=d;pos_1=u;}
  23. for (int v=0;v<G[u].size();v++)
  24. {
  25. if (G[u][v].to!=u && !vis[G[u][v].to])
  26. {
  27. dfs(G[u][v].to,d+G[u][v].cost);
  28. }
  29. }
  30. }
  31. int main()
  32. {
  33. int t,Case=0;
  34. scanf("%d",&t);
  35. while (t--)
  36. {
  37. scanf("%d",&n);
  38. dis=-1;
  39. memset(vis,0,sizeof(vis));
  40. for (int i=0;i<=n;i++) G[i].clear();
  41. for (int i=0;i<n-1;i++)
  42. {
  43. int u,v,w;
  44. scanf("%d%d%d",&u,&v,&w);
  45. G[v].push_back(node(u,w));
  46. G[u].push_back(node(v,w));
  47. }
  48. dfs(0,0);
  49. dis=-1;
  50. memset(vis,0,sizeof(vis));
  51. dfs(pos_1,0);
  52. printf("Case %d: %d\n",++Case,dis);
  53. }
  54. return 0;
  55. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注