Atcoder abc 233 题解

A 10yen Stamp

答案就是两个数字的差/10之后上取整
记得判断res=0的情况就可以了

c++代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>using namespace std;int main()
{int x,y;scanf("%d %d",&x,&y);if(x>=y){puts("0");return 0;}else{int t=ceil(1.0*(y-x)/10);cout<<t<<endl;return 0;}
}

B - A Reverse

题意

第一行输入一个 L L L, R R R
第二行输入一个字符串 S S S
输出将字符串 S S S 的第 L L L到 R R R的子串

c++代码

#include<iostream>
#include<cstring>
#include<algorithm>using namespace std;const int N=1e5+10;
char s[N];int main()
{int l,r;cin>>l>>r;cin>>s+1;string res;int n=strlen(s+1);int mid=(l+r)>>1;for(int i=1;i<=n;i++){if(i>=l&&i<=mid) swap(s[i],s[l+r-i]);}cout<<(s+1)<<endl;
}

C - Product

题意

有 N N N个背包, 背包 i i i里面装了 L i L_i Li​个球, 每个球的的质量为 a i , j a_i,j ai​,j, 问有多少种方式可以在每个包里面选择一个球使选择的球的质量的乘积为 N N N

思路

根据题目给的数据范围可以知道所有包中的球数量的乘积最多是 1 0 5 10^5 105,所以这一题用dfs
dfs的参数:选择到了第几组,现在的乘积是多少
剪枝:当乘积大于 X X X需要剪枝
注意:需要开ll 要不然会爆掉

c++代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<unordered_map>using namespace std;typedef long long ll;const int N=1e5+10;
vector<ll> a[N];
ll sum;
int n;
int res=0;void dfs(ll pos,ll now)//选择到了第几个背包 现在背包的重量是多少
{if(pos==n)//递归出口 全部处理完{if(now==sum) res++;return ;}for(int i=0;i<a[pos].size();i++)//枚举这个背包里面选择哪一个{if((ll)a[pos][i]*now>sum) continue;//剪枝else {dfs(pos+1,now*a[pos][i]);}}
}int main()
{cin>>n>>sum;for(int i=0;i<n;i++){int s;scanf("%d",&s);for(int j=0;j<s;j++){int x;scanf("%d",&x);a[i].push_back(x);}}dfs(0,1);cout<<res<<endl;
}

D - Count Interval

题意

给一个数组 A A A和一个整数 K K K,计算有多少个 ( ( ( L L L, R R R ) ) )满足数组A的[L,R]的和为K

思路

这是一道很简单的前缀和问题
设Sum[]是数组A的前缀和数组,数组A在[L,R]的和就是Sum[r]-Sum[L-1]
那么在这里我们只需要用map记录一下前缀和出现的次数然后进行计算就可以啦
注意:记得开long long 初始化mp[0]=1(选择的L为1的时候)

c++代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<unordered_map>using namespace std;
typedef long long ll;const int N=2e5+10;ll a[N];
ll k;
int n;
unordered_map<ll,int> mp;int main()
{cin>>n>>k;mp[0]=1;ll sum=0;ll res=0;for(int i=1;i<=n;i++){ll x;scanf("%lld",&x);sum+=x;res+=mp[sum-k];mp[sum]++;}cout<<res<<endl;
}

E - Σ[k=0…10100]floor(X/10k)

题意

计算题目所给出式子的值

思路

手动模拟一下可以得到这个

 123456
+ 12345.6
+  1234.56
+   123.3456
+    12.3456
+     1.3456
--------------
=137171

这么一看思路就很简单了
倒数第一位 = 1 + 2 + 3 + 4 + 5 + 6
倒数第二位 = 1 + 2 + 3 + 4 + 5
倒数第三位 = 1 + 2 + 3 + 4
倒数第四位 = 1 + 2 + 3
倒数第五位 = 1 + 2
倒数第六位 = 1
由于数据很大 所以需要用string存下来再进行计算

c++代码

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>using namespace std;
string x;
int n;void print(vector<int> &res)
{for(auto t:res) cout<<t;cout<<endl;
}int main()
{cin>>x;n=x.size();int sum=0;for(int i=0;i<n;i++){sum+=x[i]-'0';}vector<int> res;int t=0;for(int i=n-1;i>=0;i--){t+=sum;res.push_back(t%10);t/=10;sum-=(x[i]-'0');}if(t) res.push_back(t);reverse(res.begin(),res.end());print(res);
}

F - Swap and Sort

题意

给你一个全排列 P i P_i Pi​,再给 M M M种操作,第 i i i种操作可以交换P中的 a i a_i ai​与 b i b_i bi​位置上的数字
问能否在 5 ∗ 1 0 5 5*10^5 5∗105个操作之内让P变为有序
如果可以输出顺序,不可以输出-1

思路

这一题其实是AcWing4084号码牌的简化版
先来讲讲4084
其实这一题的算法很简单只不过思路难度中等偏上
我们将这个问题想象成一个图,将可达的两个点中间连一条边
那么最终的问题就转化成了能否通过交换操作使得每个点的a[i]变为i
那就很自然的就想到了并查集(联通块+可达问题),只要在一个联通块里面,那么a[i]就是可以通过交换操作变为i的。

c++代码

#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N=110;int f[N],a[N],d[N];
int n;int find(int x)
{if(x!=f[x])f[x]=find(f[x]);return f[x];
}void merge(int a,int b)
{a=find(a);b=find(b);f[a]=b;
}int main()
{cin>>n;for(int i=1;i<=n;i++) scanf("%d",&a[i]);for(int i=1;i<=n;i++) scanf("%d",&d[i]);for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=n;i++){if(i-d[i]>=1) merge(i-d[i],i);if(i+d[i]<=n) merge(i+d[i],i);}for(int i=1;i<=n;i++){int aa=find(i);int bb=find(a[i]);if(aa!=bb){puts("NO");return 0;}}puts("YES");
}

这一题与号码牌这一题不同的就是,我们的目的就是不仅要判断能否可以通过交换使a[i]=i同时要记录交换的路径
我们的思路就是:
1.找叶子结点(用一个结点来处理整个联通块)
2.对于每个叶子结点需要讲a[i]变为i需要从哪个点转换过来(dfs 就是通过加边要a[i]与i直接可达)
dfs(u,v,fa):u是目前所在的节点 目的:s[u]=v fa是父节点为了防止递归回去
当s[u]==v说明我们找到了这个节点return true
此时我们需要将s[u]与s[j]交换 并且将这条边加入ans

c++代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<unordered_map>
#include<vector>
#include<queue>using namespace std;const int N=5e5+10,M=2*N;int f[N],s[N];
int e[M],ne[M],h[N],id[N],idx;
bool st[N];
vector<int> ans;void add(int a,int b,int c)
{e[idx]=b;ne[idx]=h[a];id[idx]=c;h[a]=idx++;
}int find(int x)
{if(x!=f[x])f[x]=find(f[x]);return f[x];
}bool merge(int a,int b)
{a=find(a);b=find(b);if(a!=b) {f[a]=b;return true;}return false;
}bool dfs(int u,int v,int fa)//将s[u]改为v
{if(s[u]==v) return true;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(j==fa) continue;if(dfs(j,v,u)){swap(s[u],s[j]);ans.push_back(id[i]);return true;}}return false;
}void leaf(int u)
{st[u]=true;for(int i=h[u];~i;i=ne[i]){int j=e[i];if(st[j])continue;leaf(j);}dfs(u,u,-1);
}int main()
{memset(h,-1,sizeof h);int n;cin>>n;for(int i=1;i<=n;i++) f[i]=i;for(int i=1;i<=n;i++) scanf("%d",&s[i]);int m;cin>>m;for(int i=1;i<=m;i++){int a,b;scanf("%d %d",&a,&b);if(merge(a,b)){add(a,b,i);add(b,a,i);}}//当(st[i],i)在一个联通块里面就可以交换--->构造生成树for(int i=1;i<=n;i++){int a=find(s[i]);int b=find(i);if(a!=b){puts("-1");return 0;}}//1.找到叶子结点for(int i=1;i<=n;i++){if(!st[i]) {leaf(i);// cout<<"i = "<<i<<endl;}}cout<<ans.size()<<endl;for(auto t:ans) cout<<t<<" ";cout<<endl;
}

G - Strongest Takahashi

题意

现在有一个NxN的方格,由‘#’与‘.’组成,现在需要消灭里面所有的‘#’,每次可以每次选择一个正整数D每次消灭D*D的矩阵中的‘#’,花费为D,求消灭所有‘#’的最小花费

思路

算法:dp
dp[x1][y1][x2][y2]:消灭(x1,y1),(x2,y2)内所有的’#'所需要的最小操作次数
每次状态转移的方式有2种,一种横着切一刀一种竖着切一刀

因为我比较懒所以就用的记忆画搜索嘿嘿

c++代码

#include<iostream>
#include<algorithm>
#include<cstring>using namespace std;const int N=60;
int n;
char g[N][N];
int f[N][N][N][N];int dp(int r1,int c1,int r2,int c2)
{if(f[r1][c1][r2][c2]!=-1) return f[r1][c1][r2][c2];if(r1==r2&&c1==c2) return g[r1][c1]=='#';f[r1][c1][r2][c2]=max(r2-r1+1,c2-c1+1);for(int i=r1;i<r2;i++) f[r1][c1][r2][c2]=min(f[r1][c1][r2][c2],dp(r1,c1,i,c2)+dp(i+1,c1,r2,c2));for(int i=c1;i<c2;i++) f[r1][c1][r2][c2]=min(f[r1][c1][r2][c2],dp(r1,c1,r2,i)+dp(r1,i+1,r2,c2));return f[r1][c1][r2][c2];
}int main()
{memset(f,-1,sizeof f);cin>>n;for(int i=1;i<=n;i++) scanf("%s",g[i]+1);cout<<dp(1,1,n,n)<<endl;
}

Ex - Manhattan Christmas Tree

题意

在二维坐标系下有N个圣诞树,每个圣诞树的坐标是( x i x_i xi​, y i y_i yi​)
接下来有Q个询问
对于每个询问给出3个整数a,b,k 你要找出距离(这里的距离指的是曼哈顿距离)在(a,b)之间距离这个点第k近的圣诞树的距离

算法

(二分+树状数组)

首先引入知识点 曼哈顿距离与切比雪夫距离的转化
因为对于曼哈顿距离我们并不是很好求第k小的距离,所以在这里引入切比雪夫距离,这样就讲第k小的距离转换成为计算矩形中点的个数
首先将坐标点( x i x_i xi​, y i y_i yi​)转化成( x i x_i xi​ + y i y_i yi​, x i x_i xi​ - y i y_i yi​)
因为树状数字中不出现0 所以在这里我们将( x i x_i xi​, y i y_i yi​)转化成( x i x_i xi​ + y i y_i yi​ + 1, x i x_i xi​ - y i y_i yi​ + 1)
怎样计算矩形中点的个数呢?
在这里采用树状数组来存储每个转化后的x坐标对应的每个y
那样每次计算dis在(a,b)的个数就是寻找 大于b的所有点的数量-大于等于a的所有点的数量
我们知道怎么求矩形中点的个数就可以开始二分了,在这里我们二分的是距离
每次check(a,b,k,mid)
首先要把(a,b)转换为切比雪夫坐标再进行计算(xx-mid,xx+mid,yy-mid,yy+mid)这个矩形中点的个数
需要注意的是 因为在这里我们需要所有的tr[i]中的点是有序的,所以我们在这里需要将切比雪夫坐标系按照y排序在进行加入树状数组中

c++代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<vector>using namespace std;typedef pair<int,int> pii;
#define x first
#define y second
const int N=2e5+10;
pii a[N];
vector<int> tr[N];
int n;int lowbit(int x)
{return x&(-x);
}void add(int x,int y)
{for(int i=x;i<N;i+=lowbit(i))tr[i].push_back(y);
}int sum(int x,int a,int b)
{int res=0;int i=x;for(;i;i-=lowbit(i)){res+=upper_bound(tr[i].begin(),tr[i].end(),b)-lower_bound(tr[i].begin(),tr[i].end(),a);}return res;
}int query(int x,int y,int a,int b)
{x=max(x,1);y=max(y,0);x=min(x,N-1);y=min(y,N-1);return sum(y,a,b)-sum(x-1,a,b);
}bool check(int x,int y,int k,int mid)
{int xx=x+y+1;int yy=x-y+1;return query(xx-mid,xx+mid,yy-mid,yy+mid)>=k;
}static bool cmp(pii a,pii b)
{return a.y<b.y;
}int main()
{int n;cin>>n;for(int i=1;i<=n;i++){int x,y;scanf("%d %d",&x,&y);a[i]=make_pair(x+y+1,x-y+1);}sort(a+1,a+n+1,cmp);for(int i=1;i<=n;i++){add(a[i].x,a[i].y);}int q;cin>>q;while(q--){int a,b,k;scanf("%d %d %d",&a,&b,&k);int l=0,r=2e5+10;while(l<r){int mid=(l+r)>>1;if(check(a,b,k,mid)) r=mid;else l=mid+1;}printf("%d\n",r);   }
}

Atcoder abc 233 题解相关推荐

  1. AtCoder ABC 250 总结

    AtCoder ABC 250 总结 总体 连续若干次一样的结果:30min 切前 4 题,剩下卡在 T5 这几次卡在 T5 都是一次比一次接近, 什么 dp 前缀和打挂,精度被卡,能水过的题连水法都 ...

  2. AtCoder beginner contest 43 (ABC 43)题解

    B题:Unhappy HackingProblem 给定一个字符串和一个空串,字符串只包含01B三种字符,从字符串首开始,若为0/1则在空串后添加0/1; 若为B且字符串不为空,则删除字符串最后一个字 ...

  3. AtCoder ABC 127F Absolute Minima

    题目链接:https://atcoder.jp/contests/abc127/tasks/abc127_f 题目大意 初始状态下$f(x) = 0$,现在有 2 种模式的询问,第一种以"1 ...

  4. AtCoder abc256全题解(区间合并模板、矩阵快速幂优化dp、线段树……)

    文章目录 A B C-枚举 D-区间合并模板 E-图论建模,函数图的性质 题意 思路 代码 F-树状数组 题意 思路 代码 G-矩阵快速幂优化dp H-线段树 思路 实现 传送门 本文CSDN 本文j ...

  5. Atcoder abc A~E

    ABC 265 A~E A 题意:你要买 n 个苹果,买 1 个要 x 元,买 3 个要 y 元,问最少要花多少钱 解法:判断 3*x 是否小于 y,然后输出 Code : # include < ...

  6. AtCoder - ABC 167 - E(数学推理+组合数)

    E - Colorful Blocks 题意: 有 m 种颜色,给 n 个方块染色,可以不使用所有颜色,要求最多有 k 对相邻方块同色.问染色的总情况,最终结果模  998244353. 数据范围: ...

  7. AtCoder - ABC 178 - C~F

    C - Ubiquity(容斥原理/DP) 题意: 求满足以下条件的长为 n 的不同序列的个数: 1.0 ≤  ≤9 2.序列中至少有一个 =0 3.序列中至少有一个 =9 答案对 +7 取模. 数据 ...

  8. 蓝桥杯国赛 C/C++ ABC组题解(第四届 ~ 第十二届)

    2020年第十一届蓝桥杯国赛 题号 类型 C++ A组 C++ B组 C++ C组 试题A 结果填空 合数个数 美丽的 2 美丽的 2 试题B 结果填空 含 2 天数 (日期处理) 扩散 (BFS) ...

  9. AtCoder ABC 249

    A Jogging 没看清楚题 a不是移速 所以卡了十分钟 语法题 int main() {int a, b, c, d, e, f, x;cin >> a >> b > ...

最新文章

  1. java htmldecoder_HTMLDecoder——开头的HTML编码的解码工具类(java)
  2. 准备:新V8即将到来,Node.js的性能正在改变
  3. JavaScript 模拟事件触发
  4. Icarus Verilog与GTKWave简介及其下载安装
  5. ubuntu重置面板
  6. 在代码中设置TextView 的字体颜色
  7. 前端捕捉轨迹_一篇文章教你如何捕获前端错误
  8. sql server 2008语言基础: 连接查询习题
  9. Java之常用函数笔记
  10. Java中关于HashMap的使用和遍历
  11. 汉诺塔函数python_Python使用函数模拟“汉诺塔”过程
  12. 数字化图书馆软硬件环境要求-转自《博奥智源》
  13. 《鸟哥 Linux 私房菜》560 页新书首发!完整中文版 PDF 下载
  14. WordPress和October
  15. 第一章 HTML基础
  16. 【网页制作】CSS文本和字体属性讲解【附讲解视频】
  17. 关于Jupyter Notebook的环境配置
  18. 阿里自然语言处理部总监分享:NLP技术的应用及思考
  19. 已知坐标用matlab画图,已知45个点X Y Z的坐标值已知,如何用matlab画出网格图,每......
  20. spark submit参数及调试

热门文章

  1. 八年级使用计算机的教案,苏科版信息技术八年级1.2.2《用计算机制作逐帧动画》教案1.doc...
  2. NVIDIA发布Tegra 4:四核A15+72核心GPU
  3. 入门深度学习OCR(Optical character recognition)开发
  4. Python中的scatter
  5. Allegro导出DXF文件
  6. vue项目SEO优化以及生成sitemap.xml
  7. Java并发原理抽丝剥茧,读写锁ReadWriteLock实现深入剖析
  8. Microbiome:杨树内生和根际微生物组结构
  9. CASAIM高精度自动化三维扫描系统检测塑料件,自动检测形位公差
  10. stm32用库函数控制一位共阳数码管以及共阴数码管