入门赛8
来源:互联网 发布:微信数据转移到sd卡 编辑:程序博客网 时间:2024/05/19 19:42
- 前言
- T1 k-Factorization
- 题面
- 题意
- 思路
- 代码
- 小结
- T2 Odd sum
- 题面
- 题意
- 思路
- 代码
- 小结
- T3 Minimal string
- 题面
- 题意
- 思路
- WA点
- 代码
- 小结
- T4 Broken BST
- 题面
- 题意
- 思路
- 代码
- 小结
- T5 Array Queries
- 题面
- 题意
- 思路
- 代码
- 小结
- T6 Mice and Holes
- 题面
- 题意
- 思路
- 代码
- 小结
- 总结
前言
比赛,比赛,还是比赛。
本赛涉及题目:
A: [k-Factorization]B: [Odd sum]
C: [Minimal string]
D: [Broken BST]
E: [Array Queries]
F: [Mice and Holes]
T1 k-Factorization
题面
原题地址: [A]
题意
将n分解成k个数的积,如果不可能输出-1。
思路
质因数分解…
代码
#include<bits/stdc++.h>using namespace std;int main(){ int n,k,a[100],cut=0,i,ans=1; memset(a,0,sizeof(a)); scanf("%d%d",&n,&k); for(i=2;i<=n;i++)//分解质因数; { if(n%i) continue; while(n%i==0) { a[++a[0]]=i; n/=i; } } if(a[0]<k) printf("-1"); else { for(i=1;i<k;i++) printf("%d ",a[i]); for(;i<=a[0];i++) ans*=a[i];//将多余的质因数变成一个; printf("%d",ans); } return 0;}
小结
水题*1。
T2 Odd sum
题面
原题地址: [B]
题意
在n个数中删除几个数,使剩下的数的和为奇数且最大。
思路
先正奇偶数都选,如果是奇数,直接输出,否则判断一下最接近0的正奇数与负奇数,选择删还是加(此时只要再删除(加上)一个奇数,和就会变成奇数,删或加由上述两值的abs值决定)。
代码
#include<bits/stdc++.h>#define inf 0x3f3f3f3fusing namespace std;int n,x,i,ans,a[1000000],cut,maxn,minn,sum;bool cmp(int x,int y){ return x>y; }int main(){ maxn=-inf; minn=inf; for(scanf("%d",&n),i=0;i<n;i++) { scanf("%d",&x); if(x>0) sum+=x; if(x&1&&x<0&&x>maxn) maxn=x; if(x&1&&x>0&&x<minn) minn=x; } sum&1?printf("%d",sum):printf("%d",max(sum-minn,sum+maxn)); return 0;}
小结
水题*2。
T3 Minimal string
题面
原题地址: [C]
题意
将一个字符串通过入栈出栈的操作,使出栈后得到的字符串字典序最小。
思路
贪心…
WA点
将当前最优字母出栈后,还要在判断栈顶字母,是不是还是最优,而不是直接再入栈。
代码
#include<bits/stdc++.h>using namespace std;stack<char> t;queue<char> s;map<char,int> num;char ch='a',c;bool p;int main(){ num[char('z'+1)]=1; while(~scanf("%c",&c)&&c!='\n') s.push(c),num[c]++; while(num[ch]==0) ch++; while(!s.empty()) { t.push(s.front()); s.pop(); num[t.top()]--; p=false; while(!t.empty())//这一段while是重点,回判栈顶; { for(c=t.top()-1;c>='a';c--) if(num[c]) p=true; if(p) break; printf("%c",t.top());//贪心:当前最优出栈; t.pop(); } } while(!t.empty()) printf("%c",t.top()),t.pop(); return 0;}
小结
水题*3,不过很可惜我在WA点WA了n次~~(STL自己研究)
T4 Broken BST
题面
原题地址: [D]
题意
给每个点的权值,左右孩子,问用BST搜索法有几个数搜索不到。搜索的数为每一个点的权值。
(权值可以重复,一个权值k被搜到了,其他的相等权值k都当可以搜到)。
思路
如果点i的权值k无法搜到,而点p的权值k可以搜到,还是算k可以搜到(两个k都算可以搜到),所以只用把所有可以搜到的数拉出来,剩下是就是不可搜到的。
这个数如果比它到根节点的所有向右的权值的maxn大,所有向左的minn小,这个数就是可以搜到的(不包括这个点的权值)。
代码
#include<bits/stdc++.h>#define N 100000#define inf 0x3f3f3f3fusing namespace std;struct Tree{ int num,l,r;}tr[N+5];bool p[N+5];int n,i,ans;map<int,int> m;map<int,int>::iterator it;void dfs(int i,int maxn,int minn){ if(i==-1) return; if(tr[i].num>=maxn&&tr[i].num<=minn) m[tr[i].num]=0;//可以搜到,这个数(包括其他点的相等权值)就不是不能搜到的点; dfs(tr[i].l,maxn,min(minn,tr[i].num));//向左更新minn; dfs(tr[i].r,max(maxn,tr[i].num),minn);//向右更新maxn;}int main(){ m.clear(); memset(p,true,sizeof(p)); for(scanf("%d",&n),i=1;i<=n;i++) { scanf("%d%d%d",&tr[i].num,&tr[i].l,&tr[i].r); if(tr[i].l!=-1) p[tr[i].l]=false;//找出根节点; if(tr[i].r!=-1) p[tr[i].r]=false; m[tr[i].num]++;//出现的数; }i=1; while(!p[i]) i++; dfs(i,-inf,inf);//搜索; for(it=m.begin();it!=m.end();it++)//寻找有多少个点没被搜到; { ans+=it->second; } printf("%d",ans); return 0;}
小结
权值有重复,一个可以搜到就算全部可以搜到,这一点是重点!!
T5 Array Queries
题面
原题地址: [E]
题意
有n个数和m个询问,p在经过多少次操作之后会>n。
操作:p=p+a[p]+k。
思路
由于p可以从后往前推,所以DP是可以的,而题意也让人想到了模拟,但因为数据范围,DP->MLE,模拟->TLE,所以使用分治,k<=sqrt(n)时DP,其余的用模拟。
原理:k小时,模拟的次数较多,易超时,所以用O(n)的DP预处理。
代码
#include<bits/stdc++.h>using namespace std;int ans,a[100005][351],p,k,n,m,i,j;int main(){ for(scanf("%d",&n),i=1;i<=n;i++) scanf("%d",&a[i][0]); for(j=1;j<=350;j++)//k<=350时DP; { for(i=n;i>=1;i--) { a[i][0]+i+j>n?a[i][j]=1:a[i][j]=a[a[i][0]+i+j][j]+1; } } for(scanf("%d",&m),i=1;i<=m;i++) { scanf("%d%d",&p,&k); if(k<=350) printf("%d\n",a[p][k]); else//其余模拟; { ans=0; while(a[p][0]+p+k<=n) { p=a[p][0]+p+k; ans++; } printf("%d\n",ans+1); } } return 0;}
小结
水是水,但不知多久没打分治了,差点没想起这种算法。
T6 Mice and Holes
题面
原题地址: [F]
题意
有n之老鼠,m个洞,每个洞都有其容量上限,问所有老鼠进洞所需的最小距离和。
思路
设dp[i][j]表示前i个洞进了j只老鼠的最小距离和,易知dp[i][j]=min(dp[i][j],dp[i-1][k]+sum[i][j]-sum[i-1][k]),0<=k<=j。显然我们暴搜的复杂度为n*m*k,但我们知道,sum[i][k]会被多次枚举,而且dp[i][j],是一个定值,所以我们只要知道sum[i][k]的区间最大值就行了,此时我们可以用单调队列来优化区间多次求最大值。
(好吧,我承认我不会讲)
代码
#include<bits/stdc++.h>#define LL long long#define inf 0x3f3f3f3f#define N 5000using namespace std;pair<LL,LL> hole[N+5];LL mice[N+5],sum[N+5],pre[N+5],dp[N+5][N+5],que[N+5],n,m,i,j,l,r;int main(){ for(scanf("%d%d",&n,&m),i=1;i<=n;i++) scanf("%lld",&mice[i]); for(i=1;i<=m;i++) scanf("%lld%lld",&hole[i].first,&hole[i].second); sort(mice+1,mice+n+1),sort(hole+1,hole+m+1);memset(dp,inf,sizeof(dp)); for(i=1;i<=m;i++) pre[i]=pre[i-1]+hole[i].second; if(pre[m]<n) return 0*puts("-1"); for(dp[0][0]=0,i=1;i<=m;i++) { dp[i][0]=l=r=que[++r]=0; for(j=1;j<=pre[i]&&j<=n;j++) { dp[i][j]=dp[i-1][j];que[++r]=j; sum[j]=sum[j-1]+llabs(mice[j]-hole[i].first); while(j-que[l]>hole[i].second) l++; while(l<r&&dp[i-1][que[l]]-sum[que[l]]>dp[i-1][j]-sum[j]) l++; dp[i][j]=min(dp[i][j],sum[j]+dp[i-1][que[l]]-sum[que[l]]); } } printf("%lld\n",dp[m][n]);}
小结
单调队列不会,状态转移方程不会,什么都不会!!!
总结
每一题都WA在莫名其妙的地方,搞得我超级慌~~
- 入门赛8
- 入门赛2
- 入门赛3
- 入门赛4
- 入门赛5
- 入门赛6
- 入门赛7
- 入门赛9
- 入门赛10
- 入门赛11
- 入门赛12
- PHP入门学习8
- Junit3.8入门
- Python入门8
- Windows 8 操作系统入门
- JMeter入门8---集合点
- Android 8天入门
- 8-10 EXT入门
- java--byte
- viewpager
- winsparkle
- 一 单例模式
- vs2010+QT开发配置
- 入门赛8
- Eclipse内置SVN下载
- 使用Spring的@Scheduled实现定时任务以及解决无法执行定时任务
- opencv如何读取图像、视频(基于Python语言)
- 【数据平台】Eclipse+Scala开发环境(本机和集群两个运行模式)
- JAVA项目实战,接口集合的数据形式的调整
- Java语法--通配符的上界通配符和下界通配符
- Faster-RCNN实现物体检测
- Android动画之animation-list实现逐帧动画