A.题意:通过加奇数减偶数的操作从a到b最少需要几步

签到题

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=;
  14.  
  15. int main(){
  16. int n;
  17. scanf("%d",&n);
  18. for(int i=;i<n;i++){
  19. ll a,b;
  20. scanf("%lld%lld",&a,&b);
  21. ll c=b-a;
  22. if(c==){
  23. printf("0\n");
  24. }else if(c>&&c%==){
  25. printf("2\n");
  26. }else if(c<&&c%!=){
  27. printf("2\n");
  28. }
  29. else printf("1\n");
  30. }
  31.  
  32. return ;
  33. }

B.题意:有一个数组p,你可以任意次交换a[pi]和a[pi+1],问能不能把数组变成一个非严格上升的子序列。

解:很明显,如果p数组中有连续的一段,那么这一段数字就是可以任意交换的,把连续的若干段都进行排序,就已经尽最大可能满足题目要求了,在与满足条件的数组比较一下即可。

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=+;
  14.  
  15. void merge_sort(int *a,int x,int y,int *t){
  16. if(y-x>){
  17. int m=x+(y-x)/;
  18. int p=x,q=m,i=x;
  19. merge_sort(a,x,m,t);
  20. merge_sort(a,m,y,t);
  21. while(p<m||q<y){
  22. if(q>=y||(p<m&&a[p]<=a[q]))t[i++]=a[p++];
  23. else t[i++]=a[q++];
  24. }
  25. for(i=x;i<y;i++)a[i]=t[i];
  26. }
  27. }
  28.  
  29. int a[maxn],b[maxn],c[maxn],d[maxn],e[maxn];
  30.  
  31. int main(){
  32. int t;
  33. scanf("%d",&t);
  34. while(t--){
  35. int n,m;
  36. scanf("%d%d",&n,&m);
  37. for(int i=;i<n;i++){
  38. scanf("%d",&a[i]);
  39. d[i]=a[i];
  40. }
  41.  
  42. for(int i=;i<=n;i++)c[i]=;
  43. for(int i=;i<m;i++){
  44. scanf("%d",&b[i]);
  45. b[i]--;
  46. c[b[i]]=;
  47. }
  48. c[n]=;
  49. int l,r;
  50. l=r=-;
  51. for(int i=;i<=n;i++){
  52. if(c[i]==){
  53. if(l==-){
  54. l=i;
  55. }
  56. }else{
  57. if(l!=-){
  58. merge_sort(a,l,i+,e);
  59. l=-;
  60. }
  61. }
  62. }
  63. sort(d,d+n);
  64. int o=;
  65. for(int i=;i<n;i++){
  66. if(a[i]!=d[i])o=;
  67. }
  68. if(o)printf("YES\n");
  69. else printf("NO\n");
  70. }
  71. return ;
  72. }

C.题意:求每个字母出现的次数

解:因为错误的顺序并不会影响结果,所以直接先处理短的,再处理长的。

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=*1e5+;
  14.  
  15. int a[maxn];
  16. char s[maxn];
  17. int w[],e[];
  18. int main(){
  19. int t;
  20. scanf("%d",&t);
  21. while(t--){
  22. int n,m;
  23. scanf("%d%d",&n,&m);
  24. getchar();
  25. scanf("%s",s);
  26. for(int i=;i<m;i++){
  27. scanf("%d",&a[i]);
  28. }
  29. sort(a,a+m);
  30. for(int i=;i<;i++){
  31. w[i]=e[i]=;
  32. }
  33. int j=;
  34. for(int i=;i<n;i++){
  35. w[s[i]-'a']++;
  36. while(a[j]-==i&&j<m){
  37. j++;
  38. for(int k=;k<;k++){
  39. e[k]+=w[k];
  40. }
  41. }
  42. }
  43.  
  44. for(int k=;k<;k++){
  45. e[k]+=w[k];
  46. }
  47.  
  48. for(int i=;i<;i++){
  49. if(i<)printf("%d ",e[i]);
  50. else printf("%d\n",e[i]);
  51. }
  52. }
  53. return ;
  54. }

D.题意:给a,b,c。每一步你可以让abc中任意一个加1或者减1.求让c是b的倍数且b是a的倍数最少需要多少步?

解:首先考虑这样一个问题,题目其他条件不变,只把c去掉。那么问题就变成了给a,b。每一步你可以让ab中任意一个加1或者减1.求让b是a的倍数最少需要多少步?

  两个做法:1,很明显,如果a确定了,b也就是确定的。那么就可以通过枚举a来确定b。时间复杂度为枚举a的时间复杂度。2,如果b确定,那么a就是b的因子中最接近原来的a的那个,说明a也是确定的。时间复杂度为枚举b的时间复杂度*求b因子的时间复杂度。

  回到原题:做法就比较显而易见了,两个做法:1.显然b是最关键的一个字。所以枚举b,a用b的因子确定,c可以直接确定。时间复杂度为枚举b的时间复杂度*求b因子的时间复杂度。2.枚举a,这时因为有c的存在,显然不能直接确定b是多少,所以枚举b为a的倍数,对于每个b都可以确定唯一一个c。时间复杂度为枚举a*枚举a的倍数O(nlogn)

  下代码为做法2,需要注意的是枚举b时需要比1e4大

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=*1e5+;
  14.  
  15. int main(){
  16. int t;
  17. scanf("%d",&t);
  18. while(t--){
  19. int m=1e5;
  20. int a,b,c;
  21. int a1,b1,c1;
  22. scanf("%d%d%d",&a,&b,&c);
  23. for(int i=;i<=1e4;i++){
  24. int num=;
  25. for(int j=i;j<=2e4;j+=i){
  26. num=;
  27. num+=max(i-a,a-i);
  28. num+=max(j-b,b-j);
  29.  
  30. int k;
  31. if(c%j>j/){
  32. k=(c+j-)/j*j;
  33. }else{
  34. k=c/j*j;
  35. }
  36. if(k<j)k=j;
  37. num+=max(k-c,c-k);
  38. if(num<m){
  39. m=num;
  40. a1=i;
  41. b1=j;
  42. c1=k;
  43. }
  44. }
  45. }
  46. printf("%d\n",m);
  47. printf("%d %d %d\n",a1,b1,c1);
  48. }
  49. return ;
  50. }

E.题意,一个n节点的二叉树,能不能让所有节点的深度和为m,如果能,构造出这棵树。

解:1.很明显,如果一颗n节点树是一条链,那么此时的深度和为n节点树所能达到的上线。

  2.同理,如果一颗n节点的二叉树为完全二叉树,那么此时的深度和为n节点树所能达到的下线。

  3.如何证明下线到上线之间每个数字都是可取的呢,假设现在又n个节点形成一条链,深度和为m,如何构造一颗深度和为m-1的树,答:最深 的那个节点移动到上一层。如何构造一颗深度和为m-2的树?答:还是刚才那个节点再向上移动一层。如此反复,直到此节点不能向上移动,那么开始移动下个一最深的节点。每一步都使得深度和减一,并且由一条链开始,最所有节点无法移动时会变成一颗完全二叉树。

  4.如何模拟这个过程构造树。如果直接模拟这个过程是非常难模拟的,这道题的关键字是深度,所以我再这个模拟过程中去掉其他东西,只保留每个深度有多少节点,最后问题就变成了已知每个深度有多少节点,构造一颗二叉树。

  5.补充:代码中的b数组代表第i层最多容纳b[i]个节点,那么有一行为if(b[i]>10000)b[i]=10000;时什么意思,答,因为是二叉树,所以b每次*2,有5000个节点,也就是最深为5000层,早就爆int了,但同时发现,只有5000个节点,也就是说在这个做法中最多的时候一层只有2500个。所以当b>2500的时候,需要赋值为一个大于2500的数字就能保证准确性。

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=*1e5+;
  14.  
  15. int a[maxn];
  16. int b[maxn];
  17. int c[maxn];
  18. int main(){
  19. int t;
  20. scanf("%d",&t);
  21. while(t--){
  22. ll n,d;
  23. ll s,x;
  24. scanf("%lld%lld",&n,&d);
  25. s=(+n-)*n/;
  26. x=;
  27. ll nn=n;
  28. for(int i=,j=;nn>;i*=,j++){
  29. if(nn>=i){
  30. x+=i*j;
  31. }else{
  32. x+=nn*j;
  33. }
  34. nn-=i;
  35. }
  36. //printf("%lld %lld \n",x,s);
  37. if(x<=d&&d<=s){
  38. printf("YES\n");
  39.  
  40. for(int i=;i<n;i++){
  41. a[i]=;
  42. if(i==)b[i]=;
  43. else b[i]=b[i-]*;
  44. if(b[i]>)b[i]=;
  45. }
  46. int j=n-;
  47. int jj=n-;
  48. int qwe=s-d;
  49.  
  50. for(int i=;i<qwe;i++){
  51. //printf("%d %d \n",a[j-1],b[j-1]);
  52. if(a[j-]>=b[j-]){
  53. j=jj;
  54. //printf(".....");
  55. }
  56. if(j==jj&&a[jj]==){
  57. jj--;
  58. }
  59.  
  60. a[j]--;
  61. a[--j]++;
  62. /*
  63. for(int k=0;k<=jj;k++){
  64. printf("%d ",a[k]);
  65. }printf("\n");
  66. */
  67. }
  68.  
  69. int k=;
  70. int kk=;
  71. for(int i=;i<=jj;i++){
  72. for(int j=;j<a[i];j++){
  73. k++;
  74. c[k]=kk;
  75. if(j%==)kk--;
  76. }
  77. kk=k;
  78. }
  79. for(int i=;i<=n;i++){
  80. printf("%d ",c[i]);
  81. }
  82. printf("\n");
  83. }else printf("NO\n");
  84. }
  85. return ;
  86. }

F.

解:1.首先是最明显的一个条件,两个点要么会相遇,要么不会相遇,且不会相遇的两点在时间为0时最近。

  2.最简单的思路为枚举i枚举j时间复杂度为n2但显然超时,那么就只能线性枚举,当我们枚举到第i个的时候,前面的点有的在我们左边,有的在我们右边,有的往左走,有的往右走,有的比i点快,有的比i点满。何解?

    2.1首先发现,枚举i枚举j和ij的顺序无关,所以我们可以给数组按位置排序,排序后枚举到第i个点时,前面的点都在i的左侧。

    2.2说起运动,就有相对运动和绝对运动,题目中描述了一种相对坐标系的运动,如果给所有点都加上一个+1e9的速度,明显所有点的相对位置时不会变的,但是都变成了向右移动。这时发现相遇是否之和速度大小有关系,和值是多少关系不大,所以明显可以对速度离散化。

    2.3假设遍历到第i个点位置为x,速度为v,我们要得到是前i-1个点中不能与之相遇的点与i点的距离差的和。那么就需要知道这个样的点有多少个,假设为y,以及这些点到坐标原点0之间的距离和sum。那么前i-1个点中不能与之相遇的点与i点的距离差的和=x*y-sum

  1. #include <algorithm>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cstdio>
  5. #include <vector>
  6. #include <cmath>
  7. #include <queue>
  8. #include <deque>
  9. #include <map>
  10. using namespace std;
  11. typedef long long ll;
  12. const double inf=1e20;
  13. const int maxn=2e5+;
  14.  
  15. #define ls l,m,rt<<1;
  16. #define rs m+1,,r,rt>>1|1;
  17.  
  18. ll n;
  19. struct aa{
  20. ll a,v;
  21. aa(){}
  22. aa(ll a_,ll v_):a(a_),v(v_){}
  23. }a[maxn];
  24.  
  25. bool cmp(aa a,aa b){
  26. return a.a<b.a;
  27. }
  28.  
  29. ll m;
  30. ll t[maxn];
  31. void Init_hash(){
  32. for(int i=;i<=n;i++){
  33. t[i]=a[i-].v;
  34. }
  35. sort(t+,t++n);
  36. m=unique(t+,t++n)-t-;
  37. }
  38.  
  39. int hashh(int x){
  40. return lower_bound(t+,t++m,x)-t;
  41. }
  42.  
  43. ll sum[maxn<<];
  44.  
  45. void pushup(int rt){
  46. sum[rt]=sum[rt<<]+sum[rt<<|];
  47. }
  48. void build(ll l,ll r,ll rt){
  49. if(l==r){
  50. sum[rt]=;
  51. return ;
  52. }
  53. ll m=(l+r)/;
  54. build(l,m,rt<<);
  55. build(m+,r,rt<<|);
  56. pushup(rt);
  57. }
  58. void update(ll L,ll C,ll l,ll r,ll rt){
  59. if(l==r){
  60. sum[rt]+=C;
  61. return;
  62. }
  63. ll m=(l+r)>>;
  64. if(L<=m)update(L,C,l,m,rt<<);
  65. else update(L,C,m+,r,rt<<|);
  66. pushup(rt);
  67. }
  68. ll query(ll L,ll R,ll l,ll r,ll rt){
  69. if(L<=l&&r<=R)return sum[rt];
  70. ll m=(l+r)/;
  71. ll ans=;
  72. if(L<=m)ans+=query(L,R,l,m,rt<<);
  73. if(R> m)ans+=query(L,R,m+,r,rt<<|);
  74. return ans;
  75. }
  76.  
  77. ll sum2[maxn<<];
  78.  
  79. void pushup2(int rt){
  80. sum2[rt]=sum2[rt<<]+sum2[rt<<|];
  81. }
  82. void build2(ll l,ll r,ll rt){
  83. if(l==r){
  84. sum2[rt]=;
  85. return ;
  86. }
  87. ll m=(l+r)/;
  88. build2(l,m,rt<<);
  89. build2(m+,r,rt<<|);
  90. pushup2(rt);
  91. }
  92. void update2(ll L,ll C,ll l,ll r,ll rt){
  93. if(l==r){
  94. sum2[rt]+=C;
  95. return;
  96. }
  97. ll m=(l+r)>>;
  98. if(L<=m)update2(L,C,l,m,rt<<);
  99. else update2(L,C,m+,r,rt<<|);
  100. pushup2(rt);
  101. }
  102. ll query2(ll L,ll R,ll l,ll r,ll rt){
  103. if(L<=l&&r<=R)return sum2[rt];
  104. ll m=(l+r)/;
  105. ll ans=;
  106. if(L<=m)ans+=query2(L,R,l,m,rt<<);
  107. if(R> m)ans+=query2(L,R,m+,r,rt<<|);
  108. return ans;
  109. }
  110.  
  111. int main(){
  112. scanf("%lld",&n);
  113. for(int i=;i<n;i++){
  114. scanf("%lld",&a[i].a);
  115. }
  116. for(int i=;i<n;i++){
  117. scanf("%lld",&a[i].v);
  118. }
  119.  
  120. Init_hash();
  121. sort(a,a+n,cmp);
  122.  
  123. build(,n,);
  124. build2(,n,);
  125.  
  126. ll num=;
  127. for(int i=;i<n;i++){
  128. ll vv=hashh(a[i].v);
  129.  
  130. ll x=query(,vv,,n,);
  131. ll summ=query2(,vv,,n,);
  132. num+=(x*a[i].a-summ);
  133. //printf("%lld %lld...\n",x,summ);
  134.  
  135. update(vv,,,n,);
  136. update2(vv,a[i].a,,n,);
  137. //printf("%lld\n",num);
  138. }
  139. printf("%lld\n",num);
  140. return ;
  141. }

Codeforces Round #624 (Div. 3)的更多相关文章

  1. Codeforces Round #624 (Div. 3)(题解)

    Codeforces Round #624 (Div.3) 题目地址:https://codeforces.ml/contest/1311 B题:WeirdSort 题意:给出含有n个元素的数组a,和 ...

  2. Codeforces Round #624 (Div. 3) F. Moving Points 题解

    第一次写博客 ,请多指教! 翻了翻前面的题解发现都是用树状数组来做,这里更新一个 线段树+离散化的做法: 其实这道题是没有必要用线段树的,树状数组就能够解决.但是个人感觉把线段树用熟了会比树状数组更有 ...

  3. Codeforces Round #624 (Div. 3) C. Perform the Combo(前缀和)

    You want to perform the combo on your opponent in one popular fighting game. The combo is the string ...

  4. 详细讲解Codeforces Round #624 (Div. 3) E. Construct the Binary Tree(构造二叉树)

    题意:给定节点数n和所有节点的深度总和d,问能否构造出这样的二叉树.能,则输出“YES”,并且输出n-1个节点的父节点(节点1为根节点). 题解:n个节点构成的二叉树中,完全(满)二叉树的深度总和最小 ...

  5. 详细讲解Codeforces Round #624 (Div. 3) F. Moving Points

    题意:给定n个点的初始坐标x和速度v(保证n个点的初始坐标互不相同), d(i,j)是第i个和第j个点之间任意某个时刻的最小距离,求出n个点中任意一对点的d(i,j)的总和. 题解:可以理解,两个点中 ...

  6. Codeforces Round #624 (Div. 3) B. WeirdSort(排序)

    output standard output You are given an array aa of length nn . You are also given a set of distinct ...

  7. Codeforces Round #624 (Div. 3) D. Three Integers

    You are given three integers a≤b≤ca≤b≤c . In one move, you can add +1+1 or −1−1 to any of these inte ...

  8. Codeforces Round #624 (Div. 3) A. Add Odd or Subtract Even(水题)

    You are given two positive integers aa and bb . In one move, you can change aa in the following way: ...

  9. Codeforces Round #624 (Div. 3) F

    题意: 给出n的质点,带着初位置和速度: 如果中途两点可以相遇dis(i,j)=0: 如果不可以相遇,mindis(i,j): 求n个点的两两质点最小dis(i,j)之和 思路: 因为当初位置x和速度 ...

随机推荐

  1. 使用 Visual Studio 2015 + Python3.6 + tensorflow 构建神经网络时报错:'utf-8' codec can't decode byte 0xcc in position 78: invalid continuation byte

    使用 Visual Studio 2015 + Python3.6 + tensorflow 构建神经网络时报错:'utf-8' codec can't decode byte 0xcc in pos ...

  2. yum仓库配置与内网源部署记录

    使用yum的好处主要就是在于能够自动解决软件包之间的依赖.这使得维护更加容易.这篇文章主要就是记录部署内网源的操作过程以及yum工具如何使用 因为需要.数据库要从Oracle迁移至MySQL.在部署M ...

  3. python3 ansible api 命令和playbook

    一.api代码 # coding: utf-8 import os import sys from collections import namedtuple from ansible.parsing ...

  4. k8s系列---yaml文件格式

    https://www.bejson.com/validators/yaml_editor/ yaml文件大致格式解析,通过上面这个解析网站,可以看到yaml文件解析的格式长什么样,如果知道字典和列表 ...

  5. golang-练习ATM --面向对象实现

    package utils import ( "fmt" "strings" ) type StructAtm struct { action int loop ...

  6. centos6.x下yum安装heartbeat

    [root@heartbeat ~]# uname -n #<===配置heartbeat时,节点的主机名必须和 uname -n 命令的结果要一致 heartbeat [root@heartb ...

  7. win10打开自带wifi热点共享

    win10打开自带wifi热点共享 第一步,打开网络和Internet设置 二. 找到移动热点

  8. C语言三(2)

    多重 if...else....else 结构 语法: if(条件1) { 语句1; } else if(条件2) { 语句2; } else if(条件3) { 语句3; } else { 语句N; ...

  9. SAP 对HU做转库操作,系统报错 - 系统状态HUAS是活动的 - 分析

    SAP 对HU做转库操作,系统报错 - 系统状态HUAS是活动的 - 分析 近日收到业务团队报的问题,说是对某个HU做转库时候,系统报错.如下图示: HU里有是三个序列号, 1191111034011 ...

  10. 利用ARP欺骗进行MITM(中间人攻击)

    ARP欺骗主要骑着信息收集得作用,比如可以利用欺骗获取对方流量,从流量分析你认为重要得信息 0X01  了解ARP Arp协议 ARP(Address Resolution Protocol,地址解析 ...