Codeforces Round #624 (Div. 3)
A.题意:通过加奇数减偶数的操作从a到b最少需要几步
签到题
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=;
- int main(){
- int n;
- scanf("%d",&n);
- for(int i=;i<n;i++){
- ll a,b;
- scanf("%lld%lld",&a,&b);
- ll c=b-a;
- if(c==){
- printf("0\n");
- }else if(c>&&c%==){
- printf("2\n");
- }else if(c<&&c%!=){
- printf("2\n");
- }
- else printf("1\n");
- }
- return ;
- }
B.题意:有一个数组p,你可以任意次交换a[pi]和a[pi+1],问能不能把数组变成一个非严格上升的子序列。
解:很明显,如果p数组中有连续的一段,那么这一段数字就是可以任意交换的,把连续的若干段都进行排序,就已经尽最大可能满足题目要求了,在与满足条件的数组比较一下即可。
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=+;
- void merge_sort(int *a,int x,int y,int *t){
- if(y-x>){
- int m=x+(y-x)/;
- int p=x,q=m,i=x;
- merge_sort(a,x,m,t);
- merge_sort(a,m,y,t);
- while(p<m||q<y){
- if(q>=y||(p<m&&a[p]<=a[q]))t[i++]=a[p++];
- else t[i++]=a[q++];
- }
- for(i=x;i<y;i++)a[i]=t[i];
- }
- }
- int a[maxn],b[maxn],c[maxn],d[maxn],e[maxn];
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- int n,m;
- scanf("%d%d",&n,&m);
- for(int i=;i<n;i++){
- scanf("%d",&a[i]);
- d[i]=a[i];
- }
- for(int i=;i<=n;i++)c[i]=;
- for(int i=;i<m;i++){
- scanf("%d",&b[i]);
- b[i]--;
- c[b[i]]=;
- }
- c[n]=;
- int l,r;
- l=r=-;
- for(int i=;i<=n;i++){
- if(c[i]==){
- if(l==-){
- l=i;
- }
- }else{
- if(l!=-){
- merge_sort(a,l,i+,e);
- l=-;
- }
- }
- }
- sort(d,d+n);
- int o=;
- for(int i=;i<n;i++){
- if(a[i]!=d[i])o=;
- }
- if(o)printf("YES\n");
- else printf("NO\n");
- }
- return ;
- }
C.题意:求每个字母出现的次数
解:因为错误的顺序并不会影响结果,所以直接先处理短的,再处理长的。
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=*1e5+;
- int a[maxn];
- char s[maxn];
- int w[],e[];
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- int n,m;
- scanf("%d%d",&n,&m);
- getchar();
- scanf("%s",s);
- for(int i=;i<m;i++){
- scanf("%d",&a[i]);
- }
- sort(a,a+m);
- for(int i=;i<;i++){
- w[i]=e[i]=;
- }
- int j=;
- for(int i=;i<n;i++){
- w[s[i]-'a']++;
- while(a[j]-==i&&j<m){
- j++;
- for(int k=;k<;k++){
- e[k]+=w[k];
- }
- }
- }
- for(int k=;k<;k++){
- e[k]+=w[k];
- }
- for(int i=;i<;i++){
- if(i<)printf("%d ",e[i]);
- else printf("%d\n",e[i]);
- }
- }
- return ;
- }
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大
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=*1e5+;
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- int m=1e5;
- int a,b,c;
- int a1,b1,c1;
- scanf("%d%d%d",&a,&b,&c);
- for(int i=;i<=1e4;i++){
- int num=;
- for(int j=i;j<=2e4;j+=i){
- num=;
- num+=max(i-a,a-i);
- num+=max(j-b,b-j);
- int k;
- if(c%j>j/){
- k=(c+j-)/j*j;
- }else{
- k=c/j*j;
- }
- if(k<j)k=j;
- num+=max(k-c,c-k);
- if(num<m){
- m=num;
- a1=i;
- b1=j;
- c1=k;
- }
- }
- }
- printf("%d\n",m);
- printf("%d %d %d\n",a1,b1,c1);
- }
- return ;
- }
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的数字就能保证准确性。
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=*1e5+;
- int a[maxn];
- int b[maxn];
- int c[maxn];
- int main(){
- int t;
- scanf("%d",&t);
- while(t--){
- ll n,d;
- ll s,x;
- scanf("%lld%lld",&n,&d);
- s=(+n-)*n/;
- x=;
- ll nn=n;
- for(int i=,j=;nn>;i*=,j++){
- if(nn>=i){
- x+=i*j;
- }else{
- x+=nn*j;
- }
- nn-=i;
- }
- //printf("%lld %lld \n",x,s);
- if(x<=d&&d<=s){
- printf("YES\n");
- for(int i=;i<n;i++){
- a[i]=;
- if(i==)b[i]=;
- else b[i]=b[i-]*;
- if(b[i]>)b[i]=;
- }
- int j=n-;
- int jj=n-;
- int qwe=s-d;
- for(int i=;i<qwe;i++){
- //printf("%d %d \n",a[j-1],b[j-1]);
- if(a[j-]>=b[j-]){
- j=jj;
- //printf(".....");
- }
- if(j==jj&&a[jj]==){
- jj--;
- }
- a[j]--;
- a[--j]++;
- /*
- for(int k=0;k<=jj;k++){
- printf("%d ",a[k]);
- }printf("\n");
- */
- }
- int k=;
- int kk=;
- for(int i=;i<=jj;i++){
- for(int j=;j<a[i];j++){
- k++;
- c[k]=kk;
- if(j%==)kk--;
- }
- kk=k;
- }
- for(int i=;i<=n;i++){
- printf("%d ",c[i]);
- }
- printf("\n");
- }else printf("NO\n");
- }
- return ;
- }
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
- #include <algorithm>
- #include <iostream>
- #include <cstring>
- #include <cstdio>
- #include <vector>
- #include <cmath>
- #include <queue>
- #include <deque>
- #include <map>
- using namespace std;
- typedef long long ll;
- const double inf=1e20;
- const int maxn=2e5+;
- #define ls l,m,rt<<1;
- #define rs m+1,,r,rt>>1|1;
- ll n;
- struct aa{
- ll a,v;
- aa(){}
- aa(ll a_,ll v_):a(a_),v(v_){}
- }a[maxn];
- bool cmp(aa a,aa b){
- return a.a<b.a;
- }
- ll m;
- ll t[maxn];
- void Init_hash(){
- for(int i=;i<=n;i++){
- t[i]=a[i-].v;
- }
- sort(t+,t++n);
- m=unique(t+,t++n)-t-;
- }
- int hashh(int x){
- return lower_bound(t+,t++m,x)-t;
- }
- ll sum[maxn<<];
- void pushup(int rt){
- sum[rt]=sum[rt<<]+sum[rt<<|];
- }
- void build(ll l,ll r,ll rt){
- if(l==r){
- sum[rt]=;
- return ;
- }
- ll m=(l+r)/;
- build(l,m,rt<<);
- build(m+,r,rt<<|);
- pushup(rt);
- }
- void update(ll L,ll C,ll l,ll r,ll rt){
- if(l==r){
- sum[rt]+=C;
- return;
- }
- ll m=(l+r)>>;
- if(L<=m)update(L,C,l,m,rt<<);
- else update(L,C,m+,r,rt<<|);
- pushup(rt);
- }
- ll query(ll L,ll R,ll l,ll r,ll rt){
- if(L<=l&&r<=R)return sum[rt];
- ll m=(l+r)/;
- ll ans=;
- if(L<=m)ans+=query(L,R,l,m,rt<<);
- if(R> m)ans+=query(L,R,m+,r,rt<<|);
- return ans;
- }
- ll sum2[maxn<<];
- void pushup2(int rt){
- sum2[rt]=sum2[rt<<]+sum2[rt<<|];
- }
- void build2(ll l,ll r,ll rt){
- if(l==r){
- sum2[rt]=;
- return ;
- }
- ll m=(l+r)/;
- build2(l,m,rt<<);
- build2(m+,r,rt<<|);
- pushup2(rt);
- }
- void update2(ll L,ll C,ll l,ll r,ll rt){
- if(l==r){
- sum2[rt]+=C;
- return;
- }
- ll m=(l+r)>>;
- if(L<=m)update2(L,C,l,m,rt<<);
- else update2(L,C,m+,r,rt<<|);
- pushup2(rt);
- }
- ll query2(ll L,ll R,ll l,ll r,ll rt){
- if(L<=l&&r<=R)return sum2[rt];
- ll m=(l+r)/;
- ll ans=;
- if(L<=m)ans+=query2(L,R,l,m,rt<<);
- if(R> m)ans+=query2(L,R,m+,r,rt<<|);
- return ans;
- }
- int main(){
- scanf("%lld",&n);
- for(int i=;i<n;i++){
- scanf("%lld",&a[i].a);
- }
- for(int i=;i<n;i++){
- scanf("%lld",&a[i].v);
- }
- Init_hash();
- sort(a,a+n,cmp);
- build(,n,);
- build2(,n,);
- ll num=;
- for(int i=;i<n;i++){
- ll vv=hashh(a[i].v);
- ll x=query(,vv,,n,);
- ll summ=query2(,vv,,n,);
- num+=(x*a[i].a-summ);
- //printf("%lld %lld...\n",x,summ);
- update(vv,,,n,);
- update2(vv,a[i].a,,n,);
- //printf("%lld\n",num);
- }
- printf("%lld\n",num);
- return ;
- }
Codeforces Round #624 (Div. 3)的更多相关文章
- Codeforces Round #624 (Div. 3)(题解)
Codeforces Round #624 (Div.3) 题目地址:https://codeforces.ml/contest/1311 B题:WeirdSort 题意:给出含有n个元素的数组a,和 ...
- Codeforces Round #624 (Div. 3) F. Moving Points 题解
第一次写博客 ,请多指教! 翻了翻前面的题解发现都是用树状数组来做,这里更新一个 线段树+离散化的做法: 其实这道题是没有必要用线段树的,树状数组就能够解决.但是个人感觉把线段树用熟了会比树状数组更有 ...
- 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 ...
- 详细讲解Codeforces Round #624 (Div. 3) E. Construct the Binary Tree(构造二叉树)
题意:给定节点数n和所有节点的深度总和d,问能否构造出这样的二叉树.能,则输出“YES”,并且输出n-1个节点的父节点(节点1为根节点). 题解:n个节点构成的二叉树中,完全(满)二叉树的深度总和最小 ...
- 详细讲解Codeforces Round #624 (Div. 3) F. Moving Points
题意:给定n个点的初始坐标x和速度v(保证n个点的初始坐标互不相同), d(i,j)是第i个和第j个点之间任意某个时刻的最小距离,求出n个点中任意一对点的d(i,j)的总和. 题解:可以理解,两个点中 ...
- 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 ...
- 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 ...
- 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: ...
- Codeforces Round #624 (Div. 3) F
题意: 给出n的质点,带着初位置和速度: 如果中途两点可以相遇dis(i,j)=0: 如果不可以相遇,mindis(i,j): 求n个点的两两质点最小dis(i,j)之和 思路: 因为当初位置x和速度 ...
随机推荐
- 使用 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 ...
- yum仓库配置与内网源部署记录
使用yum的好处主要就是在于能够自动解决软件包之间的依赖.这使得维护更加容易.这篇文章主要就是记录部署内网源的操作过程以及yum工具如何使用 因为需要.数据库要从Oracle迁移至MySQL.在部署M ...
- python3 ansible api 命令和playbook
一.api代码 # coding: utf-8 import os import sys from collections import namedtuple from ansible.parsing ...
- k8s系列---yaml文件格式
https://www.bejson.com/validators/yaml_editor/ yaml文件大致格式解析,通过上面这个解析网站,可以看到yaml文件解析的格式长什么样,如果知道字典和列表 ...
- golang-练习ATM --面向对象实现
package utils import ( "fmt" "strings" ) type StructAtm struct { action int loop ...
- centos6.x下yum安装heartbeat
[root@heartbeat ~]# uname -n #<===配置heartbeat时,节点的主机名必须和 uname -n 命令的结果要一致 heartbeat [root@heartb ...
- win10打开自带wifi热点共享
win10打开自带wifi热点共享 第一步,打开网络和Internet设置 二. 找到移动热点
- C语言三(2)
多重 if...else....else 结构 语法: if(条件1) { 语句1; } else if(条件2) { 语句2; } else if(条件3) { 语句3; } else { 语句N; ...
- SAP 对HU做转库操作,系统报错 - 系统状态HUAS是活动的 - 分析
SAP 对HU做转库操作,系统报错 - 系统状态HUAS是活动的 - 分析 近日收到业务团队报的问题,说是对某个HU做转库时候,系统报错.如下图示: HU里有是三个序列号, 1191111034011 ...
- 利用ARP欺骗进行MITM(中间人攻击)
ARP欺骗主要骑着信息收集得作用,比如可以利用欺骗获取对方流量,从流量分析你认为重要得信息 0X01 了解ARP Arp协议 ARP(Address Resolution Protocol,地址解析 ...