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和速度 ...
随机推荐
- JAVA ReentrantLock的使用
源码如下 对比synchronized,synchronized使用时会显示的指定一个对象(方法为调用对象,代码块会需要对象作为参数),来获取一个对象的独占锁 而ReentrantLock可能就是使用 ...
- spark读取文件机制 源码剖析
Spark数据分区调研 Spark以textFile方式读取文件源码 textFile方法位于 spark-core_2.11/org.apache.spark.api.java/JavaSparkC ...
- Python 调用 Shell命令
python程序中调用shell命令,是件很酷且常用的事情今天来总结一下 1.使用os模块 的 system 此函数会启动子进程,在子进程中执行command,并返回comman ...
- [CentOS7]sed 指定字符前后添加内容
指定字符前面添加 sed -i 's/指定的字符/需要添加的字符&/' 文件名称 修改Linux启动配置 将 GRUB_CMDLINE_LINUX="rd.lvm.lv=centos ...
- light oj 1214 - Large Division 大数除法
1214 - Large Division Given two integers, a and b, you should check whether a is divisible by b or n ...
- 【学习笔记】:JavaScript基础知识超详细总结!
目录 一.JavaScript的实现 二.JavaScript语言的特点 三.JS与HTML如何结合 四.JS中的数据类型 四.JS的原始数据类型 2.JS的引用数据类型 五.JS引用数据类型之函数 ...
- .NET CORE应用程序启动
ASP.NET Core 应用是在其 Main 方法中创建 Web 服务器的控制台应用: Main 方法调用 WebHost.CreateDefaultBuilder,通过生成器模式来创建web主机. ...
- Sql Server Proc 先看看简单吧
CREATE PRoc [名字] { @参数 数据类型, @参数 数据类型 OUTPUT[输入] } AS begin select INSERT UPDATE (SQL) end --基本语句快 - ...
- CentOS7安装MySQL报错,解决Failed to start mysqld.service: Unit not found
当输入命令 ~]# systemctl start mysql.service 要启动MySQL数据库是却是这样的提示 Failed to start mysqld.service: Unit not ...
- Python中autoescape标签使用详解
1.spaceless标签:移除html标签中的空白字符.包括空格.tab键.换行符,示例代码如下: {% spaceless %}具体内容{% endspaceless %} 2.autoescap ...