2018集训队日常训练1
5385: 树的遍历
Total Submit: 22 Accepted:16
Description
给定一棵二叉树的后序遍历和中序遍历,请你输出其层序遍历的序列。这里假设键值都是互不相等的正整数。
Input
输入第一行给出一个正整数N(<=30),是二叉树中结点的个数。第二行给出其后序遍历序列。第三行给出其中序遍历序列。数字间以空格分隔。
Output
在一行中输出该树的层序遍历的序列。数字间以1个空格分隔,行首尾不得有多余空格。
Sample Input
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
Sample Output
4 1 6 3 5 7 2
如题意所述,我们可以直接得到其前序遍历结果,所以hash一下就好了,特别大了而且成链就写一个大数吧,hash一下就好的
#include <bits/stdc++.h> using namespace std; map<int,int>M; int s[31],c[31],l; void la(int l,int r,int st,int ed,int f) {if(l<=r&&st<=ed){M[f]=c[ed];for(int i=l; i<=r; i++)if(c[ed]==s[i]){la(l,i-1,st,st+i-1-l,2*f+1),la(i+1,r,st+i-l,ed-1,2*f+2);return ;}} } int main() {cin>>l;for(int i=0;i<l;i++)cin>>c[i];for(int i=0;i<l;i++)cin>>s[i];la(0,l-1,0,l-1,0);int f=0;for(auto X:M){if(f)cout<<" ";cout<<X.second,f=1;}return 0; }
taozi的队列代码
#include<bits/stdc++.h> using namespace std; int post[1000],in[1000],Left[1000],Right[1000]; int n; int build(int L1,int R1,int L2,int R2) {if(L1>R1)return 0;int root=post[R1];int pos=L2;while(in[pos]!=root)pos++;int cnt=pos-L2;Left[root]=build(L1,L1+cnt-1,L2,pos-1);Right[root]=build(L1+cnt,R1-1,pos+1,R2);return root; } void level() {queue<int>q;q.push(post[n]);int f=0;while(!q.empty()){int u=q.front();q.pop();if(!f)printf("%d",u),f=1;else printf(" %d",u);if(Left[u])q.push(Left[u]);if(Right[u])q.push(Right[u]);} } int main() {cin>>n;for(int i=1;i<=n;i++)cin>>post[i];for(int i=1;i<=n;i++)cin>>in[i];build(1,n,1,n);level();return 0; }
5445: 中位数
总提交: 15 测试通过:2
描述
给定两个序列,都已经从小到大排序,求两个序列合并后的中位数。
所谓中位数是指:当排序后的序列元素个数是奇数时取中间值,否则去中间两个数的平均数。
你能想出O(log(m+n))复杂度的算法吗?
输入
多组数据。每组数据的:
第一行为两个整数n和m,(1<=n, m<=10000000)。
第二行由n个从小到大排序的整数。
第三行由m个从小到大排序的整数。
以EOF结束。
输出
输出中位数,保留2位小数。
样例输入
2 1
1 3
2
2 2
1 2
3 4
样例输出
提示
因本题输入数据规模较大,请使用类似以下代码输入一个整数(输入挂):
int Scan()
{
int res = 0, ch, flag = 0;
if((ch = getchar()) == '-') //判断正负
flag = 1;
else if(ch >= '0' && ch <= '9') //得到完整的数
res = ch - '0';
while((ch = getchar()) >= '0' && ch <= '9' )
res = res * 10 + ch - '0';
return flag ? -res : res;
}
枚举pos看他是第几个数,当然也会相等,所以这个还是特判一下的
为什么这样是可以的呢,因为你每个数在两个数组均会有一个位置的,我只要遍历每个数组就可以找到
mi代表当前位置,其实个数是mi+1
pos-1代表可以插入到的位置,前一个可能是相等,也可能是不等
#include<bits/stdc++.h> using namespace std; const int N=10000005; int a[N],b[N],n,m; long long L,R,zws; int la() {while(L<=R){int mi=(L+R)>>1;int pos=upper_bound(a,a+n,b[mi])-a;if(pos&&a[pos-1]==b[mi]){if(mi+pos==zws)return mi;}if(mi+pos+1<zws){if(mi==m-1)return -1;L=mi+1;}else if(mi+pos+1>zws){if(mi==0)return -1;R=mi-1;}else {return mi;}}return -1; } int lb() {while(L<=R){int mi=(L+R)>>1;int pos=upper_bound(b,b+m,a[mi])-b;if(pos&&b[pos-1]==a[mi]){if(mi+pos==zws)return mi;}if(mi+pos+1<zws){if(mi==n-1)return -1;L=mi+1;}else if(mi+pos+1>zws){if(mi==0)return -1;R=mi-1;}else {return mi;}}return -1; } int Scan() {int res = 0, ch, flag = 0;if((ch = getchar()) == '-') flag = 1;else if(ch >= '0' && ch <= '9') res = ch - '0';while((ch = getchar()) >= '0' && ch <= '9' )res = res * 10 + ch - '0';return flag ? -res : res;}int main() {while(~scanf("%d%d",&n,&m)){for(int i=0; i<n; i++)a[i]=Scan();for(int i=0; i<m; i++)b[i]=Scan();L=0,R=m-1,zws=(n+m+1)/2;int t=la();if(t==-1)L=0,R=n-1,t=lb(),t=a[t];else t=b[t];if((n+m)%2==0){zws++;L=0,R=m-1;int t1=la();if(t1==-1)L=0,R=n-1,t1=lb(),t1=a[t1];else t1=b[t1];t+=t1;}else t+=t;printf("%.2f\n",t/2.);}return 0; }
5201: 数字游戏
Total Submit: 125 Accepted:17
Description
栋栋正在和同学们玩一个数字游戏。
游戏的规则是这样的:栋栋和同学们一共n个人围坐在一圈。栋栋首先说出数字1。接下来,坐在栋栋左手边的同学要说下一个数字2。再下面的一个同学要从上一个同学说的数字往下数两个数说出来,也就是说4。下一个同学要往下数三个数,说7。依次类推。
为了使数字不至于太大,栋栋和同学们约定,当在心中数到 k-1 时,下一个数字从0开始数。例如,当k=13时,栋栋和同学们报出的前几个数依次为:
1, 2, 4, 7, 11, 3, 9, 3, 11, 7。
游戏进行了一会儿,栋栋想知道,到目前为止,他所有说出的数字的总和是多少。
Input
输入的第一行包含三个整数 n,k,T,其中 n 和 k 的意义如上面所述,T 表示到目前为止栋栋一共说出的数字个数。
Output
输出一行,包含一个整数,表示栋栋说出所有数的和。
Sample Input
Sample Output
3 13 3
Hint
17
样例说明
栋栋说出的数依次为1, 7, 9,和为17。
数据规模和约定
1 < n,k,T < 1,000,000;
可以枚举要加的值
#include<bits/stdc++.h> using namespace std;int main() {long long n,k,T,res=0,last=1;cin>>n>>k>>T;for(int i=1;i<T;i++){res+=(last+(2*i*n-n+1)*n/2)%k;last=(last+(2*i*n-n+1)*n/2)%k;}cout<<res+1;return 0; }
5202: 网络寻路
总提交: 1 测试通过:1
描述
X 国的一个网络使用若干条线路连接若干个节点。节点间的通信是双向的。某重要数据包,为了安全起见,必须恰好被转发两次到达目的地。该包可能在任意一个节点产生,我们需要知道该网络中一共有多少种不同的转发路径。
源地址和目标地址可以相同,但中间节点必须不同。
如下图所示的网络。
1 -> 2 -> 3 -> 1 是允许的
1 -> 2 -> 1 -> 2 或者 1 -> 2 -> 3 -> 2 都是非法的。
输入
输入数据的第一行为两个整数N M,分别表示节点个数和连接线路的条数(1<=N<=10000; 0<=M<=100000)。
接下去有M行,每行为两个整数 u 和 v,表示节点u 和 v 联通(1<=u,v<=N , u!=v)。
输入数据保证任意两点最多只有一条边连接,并且没有自己连自己的边,即不存在重边和自环。
输出
输出一个整数,表示满足要求的路径条数。
样例输入
3 3
1 2
2 3
1 3
样例输出
6
提示
样例输入2
4 4
1 2
2 3
3 1
1 4
样例输出2
10
可以dfs去枚举,也就是去枚举两边的点让他们不形成环
但是注意目的地可以和源地址相同,那么合法的就有以下两种情况
case1
case2
和当前节点的度有关,即这条边除了这条路带来的度的乘积
#include<bits/stdc++.h> using namespace std; const int N=100005; int d[N],u[N],v[N],n,m; int main() {long long ans=0;scanf("%d%d",&n,&m);for(int i=0; i<m; i++)scanf("%d%d",&u[i],&v[i]),d[u[i]]++,d[v[i]]++;for(int i=0; i<m; i++)if(d[u[i]]>1&&d[v[i]]>1)ans+=(d[u[i]]-1)*1LL*(d[v[i]]-1)*2;printf("%I64d\n",ans);return 0; }
5204: 小朋友排队
Total Submit: 18 Accepted:2
Description
n 个小朋友站成一排。现在要把他们按身高从低到高的顺序排列,但是每次只能交换位置相邻的两个小朋友。
每个小朋友都有一个不高兴的程度。开始的时候,所有小朋友的不高兴程度都是0。
如果某个小朋友第一次被要求交换,则他的不高兴程度增加1,如果第二次要求他交换,则他的不高兴程度增加2(即不高兴程度为3),依次类推。当要求某个小朋友第k次交换时,他的不高兴程度增加k。
请问,要让所有小朋友按从低到高排队,他们的不高兴程度之和最小是多少。
如果有两个小朋友身高一样,则他们谁站在谁前面是没有关系的。
Input
输入的第一行包含一个整数n,表示小朋友的个数。
第二行包含 n 个整数 H1 H2 … Hn,分别表示每个小朋友的身高。
Output
输出一行,包含一个整数,表示小朋友的不高兴程度和的最小值。
Sample Input
3
3 2 1
Sample Output
9
Hint
样例说明
首先交换身高为3和2的小朋友,再交换身高为3和1的小朋友,再交换身高为2和1的小朋友,每个小朋友的不高兴程度都是3,总和为9。
数据规模和约定
对于10%的数据, 1<=n<=10;
对于30%的数据, 1<=n<=1000;
对于50%的数据, 1<=n<=10000;
对于100%的数据,1<=n<=100000,0<=Hi<=1000000。
前置技能逆序对,即交换相邻两个数字的最小次数
再考虑这个问题,就是问你一个数要交换几次,这个自己可以推一下
其实就是把数倒过来正序对的个数比如 3 2 1逆序对贡献是0 1 2
倒过来1 2 3正序对贡献0 1 2,即0+2 1+1 2+0所求次数
他卡我其他求逆序对的方式,只能归并排序过的
#include <stdio.h> #include <bits/stdc++.h> using namespace std; const int N=100005; int w[N],sum[N],n; struct T {int x,num; } a[N],T[N]; void la(int l,int r) {if(r-l==1)return;int m=l+r>>1,tm=l+r>>1,tl=l,i=l;la(l,m),la(m,r);while(tl<m||tm<r){if(tm>=r||(tl<m&&a[tl].x<=a[tm].x))T[i++]=a[tl++],T[i-1].num+=tm-m;elseT[i++]=a[tm++],T[i-1].num+=m-tl;}for(int i=l; i<r; i++)a[i]=T[i]; } int main() {scanf("%d",&n);for(int i=0; i<n; i++)scanf("%d",&a[i].x),a[i].num=0;la(0,n);__int64 ans=0;for(int i=0; i<n; i++)ans+=a[i].num*1LL*(a[i].num+1)/2;printf("%I64d",ans);return 0; }
5205: 最大子阵
Total Submit: 21 Accepted:8
Description
给定一个n*m的矩阵A,求A中的一个非空子矩阵,使这个子矩阵中的元素和最大。
其中,A的子矩阵指在A中行和列均连续的一块。
Input
输入的第一行包含两个整数n, m,分别表示矩阵A的行数和列数。
接下来n行,每行m个整数,表示矩阵A。
Output
输出一行,包含一个整数,表示A中最大的子矩阵中的元素和。
Sample Input
3 3
-1 -4 3
3 4 -1
-5 -2 8
Sample Output
10
Hint
样例说明
取最后一列,和为10。
数据规模和约定
对于50%的数据,1<=n, m<=50;
对于100%的数据,1<=n, m<=500,A中每个元素的绝对值不超过5000。
想起来了要用最大字段和,但是这个dp过程还是不好想的
你可以对行或列做下前缀和,然后再求下最大字段和
基于行的dp
#include<stdio.h> const int N=505; int r[N][N]; int main() {int n,m,x;scanf("%d%d",&n,&m);for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)scanf("%d",&x),r[i][j]=r[i-1][j]+x;int ma=x,t;for(int i=1; i<=n; i++)for(int j=i; j<=n; j++){t=0;for(int k=1; k<=m; k++){t+=r[j][k]-r[i-1][k];if(t>ma)ma=t;if(t<0)t=0;}}printf("%d",ma);return 0; }
数据分布不均匀,基于列的dp跑起来比较慢
#include<stdio.h> const int N=505; int r[N][N]; int main() {int n,m,x;scanf("%d%d",&n,&m);for(int i=1; i<=n; i++)for(int j=1; j<=m; j++)scanf("%d",&x),r[i][j]=r[i][j-1]+x;int ma=x,t;for(int i=1; i<=m; i++)for(int j=i; j<=m; j++){t=0;for(int k=1; k<=n; k++){t+=r[k][j]-r[k][i-1];if(t>ma)ma=t;if(t<0)t=0;}}printf("%d",ma);return 0; }
5206: 约数倍数选卡片
Total Submit: 1 Accepted:1
Description
闲暇时,福尔摩斯和华生玩一个游戏:
在N张卡片上写有N个整数。两人轮流拿走一张卡片。要求下一个人拿的数字一定是前一个人拿的数字的约数或倍数。例如,某次福尔摩斯拿走的卡片上写着数字“6”,则接下来华生可以拿的数字包括:
1,2,3, 6,12,18,24 ....
当轮到某一方拿卡片时,没有满足要求的卡片可选,则该方为输方。
请你利用计算机的优势计算一下,在已知所有卡片上的数字和可选哪些数字的条件下,怎样选择才能保证必胜!
当选多个数字都可以必胜时,输出其中最小的数字。如果无论如何都会输,则输出-1。
Input
输入数据为2行。第一行是若干空格分开的整数(每个整数介于1~100间),表示当前剩余的所有卡片。
第二行也是若干空格分开的整数,表示可以选的数字。当然,第二行的数字必须完全包含在第一行的数字中。
Output
程序则输出必胜的招法!!
Sample Input
2 3 6
3 6
Sample Output
3
Hint
样例输入2
1 2 2 3 3 4 5
3 4 5
样例输出2
4
博弈题目,但是题目数据应该不是很多,直接dfs就过了
大概思路是这样的,因为我要选择必胜,即某个选择可以导致对手出现必败态
还要输出最小的数字,所以需要对b数组进行排序
然后需要预处理一下一个数的约数和倍数,假如这个数量级很大了,貌似就很难过了,倍数还有约数要很好的处理下,可以把有些数组直接赋值过去
#include<bits/stdc++.h> using namespace std; #define dbg(x) cout<<#x<<" = "<< (x)<< endl const int N=105; int num[N]; vector<int> b,f[N]; int dfs(int x) {for(int i=f[x].size()-1; i>=0; i--){int pp=f[x][i],t;if(num[pp]){num[pp]--,t=dfs(pp),num[pp]++;if(t)return 0;}}return 1; } void la() {for(auto X:b){if(num[X]){num[X]--;if(dfs(X)){cout<<X;return;}num[X]++;}}cout<<-1; } int main() {int x;string s;getline(cin,s);stringstream ss(s);while(ss>>x)num[x]++;getline(cin,s);stringstream st(s);while(st>>x)b.push_back(x);sort(b.begin(),b.end());for(int i=1; i<N ; i++)if(num[i])for(int j=1; j<N ; j++)if(num[j]&&(i%j==0||j%i==0))f[i].push_back(j);la();return 0; }
5200: 买不到的数目
Total Submit: 57 Accepted:43
Description
小明开了一家糖果店。他别出心裁:把水果糖包成4颗一包和7颗一包的两种。糖果不能拆包卖。
小朋友来买糖的时候,他就用这两种包装来组合。当然有些糖果数目是无法组合出来的,比如要买 10 颗糖。
你可以用计算机测试一下,在这种包装情况下,最大不能买到的数量是17。大于17的任何数字都可以用4和7组合出来。
本题的要求就是在已知两个包装的数量时,求最大不能组合出的数字。
Input
两个正整数,表示每种包装中糖的颗数(都不多于1000)
Output
一个正整数,表示最大不能买到的糖数。
如果这个数不存在,则输出-1。
Sample Input
4 7
Sample Output
17
Hint
样例输入2
3 5
样例输出2
7
题目不严谨,因为有1的时候是不存在这个数的,而且你很快会发现只有互质的时候才存在,否则是不存在的
但是是一个很好的数论
1. (x-1)(y-1)-1 不能被表示为 ax+by的形式
2. 大于等于(x-1)(y-1)都能被表示为 ax+by的形式
#include <stdio.h> int main() {int a,b;scanf("%d%d",&a,&b);printf("%d",a*b-a-b); }
转载于:https://www.cnblogs.com/BobHuang/p/8980104.html
2018集训队日常训练1相关推荐
- codeforces日常训练 C. Cutting Out - 二分搜索答案
codeforces日常训练 C. Cutting Out - 二分搜索答案 题干 You are given an array s consisting of n integers. You hav ...
- 「日常训练」Common Subexpression Elimination(UVa-12219)
今天做的题目就是抱佛脚2333 懂的都懂. 这条题目干了好几天,最后还是参考别人的代码敲出来了,但是自己独立思考了两天多,还是有收获的. 思路分析 做这条题我是先按照之前的那条题目(The SetSt ...
- 「日常训练」 Mike and Fun (CFR305D2B)
题意(CodeForces 548B) 每次对01矩阵中的一位取反,问每次操作后,单列中最长连续1的长度. 分析 非常非常简单,但是我当时训练的时候WA了四次...无力吐槽了,人间 不值得.jpg 代 ...
- 2018年日常小计汇总
2018年 从2018-10-06开始记录 十二月 2018-12-27 解析nginx日志,实时了解服务器的情况(类似于top) https://github.com/lebinh/ngxtop N ...
- 动规日常训练题解 难度普及+
9.6 动规训练 题解 ----Frosty_Jackal 定义Dpmax[i][j] 表示l~r之间最大的得分,由题意得拆环为链,将1~n的枚举范围扩大到1~2*n ,外层枚举区间长,内层枚举l, ...
- GXNU竞赛集训队第一次训练题解
2022/3/19训练题单 1352B 1512D 1368B 1542B 1399D 1372C 1400C 1352F 282C 916C 980B 214B B. Same Parity Sum ...
- 「日常训练」Bad Luck Island(Codeforces Round 301 Div.2 D)
题意与分析(CodeForces 540D) 是一道概率dp题. 不过我没把它当dp做... 我就是凭着概率的直觉写的,还好这题不算难. 这题的重点在于考虑概率:他们喜相逢的概率是多少?考虑超几何分布 ...
- 2018提高组训练Day2
A 算法 1 对于每组询问,暴力的算出每个二次函数的取值. 时间复杂度 \(O(nq)\).期望得分 \(20\) 分. 算法 2 当 \(x>0\) 时,要求 \(a_ix^2+b_ix\) ...
- 「日常训练」Skills(Codeforce Round #339 Div.2 D)
题意(CodeForces 614D) 每个人有\(n(n\le 10^5)\)个技能,技能等级都在\([0,10^9]\)的范围,每个技能有一个当前等级,所有技能的最高等级都为A.一个人的力量被记做 ...
最新文章
- modelsim中仿真波形设置的保存
- ReentrantLock实现原理深入探究
- 数字化专业人才短缺,企业亟待组建培养体系
- LeetCode 1942. 最小未被占据椅子的编号(set)
- 使用indexOf()算出长字符串中包含多少个短字符串
- MySQL高可用--MGR入门(2)组复制监控常用相关表
- [SCOI2005][BZOJ 1084]最大子矩阵
- mysql查询最接近的记录
- 华云数据:以信创云构筑自主创新长城之基
- windows xp sp3 下载地址
- Ubuntu好用的截图工具
- Massive MIMO中正交导频pilot序列的MATLAB生成方法
- 模拟一个简单的购房商贷月供计算器
- 基于微信小程序社区疫情防控系统
- Android APP的签名
- 【音视频处理】码率、帧率越高越清晰?分辨率、像素、dpi之间是什么关系?码率的真实作用,I帧、B帧、P帧是什么
- ASR技术和TTS技术含义及区别
- hive只复制表结构不复制表数据
- Mysql高级——索引篇
- gevent 实现网易云音乐歌曲下载
热门文章
- ORACLE RAC+DG 硬件配置
- category android:name=android.intent.category.DEFAULT / 惹的祸
- v8学习笔记(五) 编译过程
- Python架构(二)
- Gitlab的CI/CD初尝试
- OpenCV+yolov3实现目标检测(C++,Python)
- 软件设计模式—依赖注入
- [2019HDU多校第一场][HDU 6590][M. Code]
- P1772 [ZJOI2006]物流运输 最短路+DP
- Django的静态资源