从没打过atcoder于是vp了一场
atcoder题面比较简洁 难度比cf div2低很多
A - Three-Point Shot
题意:判断是否一个数比另一个数大3以上
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int main(){
int x,y;
cin>>x>>y;
if(max(x-y,y-x)<=2)cout<<"Yes";
else cout<<"No";
return 0;
}
B - Orthogonality
题意:给出2向量问相乘是否为0
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
scanf("%d",&b[i]);
int ans=0;
for(int i=1;i<=n;i++){
ans+=a[i]*b[i];
}
if(ans)puts("No");
else puts("Yes");
return 0;
}
C - ABC Tournament
题意:问左边最大的数 和右边最大的数 哪个小 输出位置
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e5+10;
int a[N],b[N];
int main(){
int n;
cin>>n;
n=(1<<n);
int maxl=0,l,r,maxr=0;
for(int i=1;i<=n/2;i++){
int x;
scanf("%d",&x);
if(x>maxl){
l=i,maxl=x;
}
}
for(int i=n/2+1;i<=n;i++){
int x;
scanf("%d",&x);
if(x>maxr){
r=i,maxr=x;
}
}
if(maxl>maxr)printf("%d\n",r);
else printf("%d\n",l);
return 0;
}
D - Snuke Prime
题意:一天支付c元 可以享受所有服务 和给出n个服务的起始时间和结束时间和每天的价格 问享受所有服务的情况下 付出的钱最少是多少
思路:我们把每一个服务差分为 l 到 r+1 l的值为v r+1的值为-v 那么利用前缀和可以的得到某个区间内的值(r+1-l)*v刚好就等于l到r所花费的值
就这样我们按照这样差分 并利用右端点进行排序 从前往后计算即可
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int N=2e5+10;
struct Node{
int x,v;
bool operator <(const Node &a)const{
return x<a.x;
}
}node[N*2];
int cnt=0;
map<int,bool>mp;
int main(){
int n,c;
cin>>n>>c;
for(int i=1;i<=n;i++){
int l,r,v;
scanf("%d%d%d",&l,&r,&v);
node[++cnt]={
l,v};
node[++cnt]={
r+1,-v};
}
sort(node+1,node+1+cnt);
long long ans=0,val=0;
node[++cnt]={
node[2*n].x,0};
for(int i=1;i<=cnt;i++){
//cout<<node[i].x<<" "<<val<<" "<<node[i].v<<endl;
val+=node[i].v;
if(node[i].x!=node[i+1].x&&val>=0){
if(val>=c)ans+=1ll*(node[i+1].x-node[i].x)*c;
else ans+=1ll*(node[i+1].x-node[i].x)*val;
}
}
cout<<ans;
return 0;
}
E - Peddler
题意:n个城镇m条道路 n个城镇的黄金价格给出 问从最大收益为多少 且不能在城镇买了以后又到当前一个城镇卖 必须按照路径顺序进行出售 此为有向图
思路:记忆化搜索跑一边即可 dfs返回的是该点到后续所有点能卖出的最低价格
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=3e5+10,INF=0x3f3f3f3f;
struct Edge{
int v,next;
}edge[N];
int w[N],head[N],tot,ans=-INF,st[N];
bool ok[N];
void add(int u,int v){
edge[++tot]={
v,head[u]};
head[u]=tot;
}
int dfs(int u){
if(st[u])return st[u];//返回自己儿子的最高售价
st[u]=w[u];
int maxv=-INF;
for(int i=head[u];i;i=edge[i].next){
int v=edge[i].v;
maxv=max(dfs(v),maxv);
}
ans=max(maxv-w[u],ans);
st[u]=max(st[u],maxv);
return st[u];
}
int main(){
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&w[i]);
}
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
add(u,v);
ok[v]=1;
}
for(int i=1;i<=n;i++){
if(!ok[i])dfs(i);
}
cout<<ans;
return 0;
}
F - +1-1x2
题意:给出x和y 让x变为y的最少操作数是多少 每次操作x只能+1 -1或者2
vp的时候没时间了
思路:记忆化搜索 当x>=y时我们只能进行x-y次操作
在x<y时我们可以+1或者2
共2种情况 但是如果是这样进行枚举 会爆longlong 于是采用反向搜索
在x<y 有3种情况 y-x y/2 (y)/2 y为奇数(y+1)/2
因为在y<x时我们直接得 x-y 所以主要操作都是在进行y/2直到y<x 故时间复杂度为logn
#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N=1e5+10;
unordered_map<LL,LL>mp;
LL n,m;
LL f(LL x){
if(n>=x)return mp[x]=n-x;
if(mp[x])return mp[x];
LL ans=x-n;
ans=min(ans,f(x/2)+x%2+1);
if(x%2)ans=min(ans,f(x/2+1)+2);
return mp[x]=ans;
}
int main(){
cin>>n>>m;
cout<<f(m);
}