10.3离线赛
来源:互联网 发布:乐乎公寓 百子湾店 编辑:程序博客网 时间:2024/06/05 03:12
预分:200 实分:175
写书
应得:100 实得:100
题意:计算1到n的数字出现个数
数据:对于100%,n∈[1,1e9];
小学奥数题,没有必要多想,一位数两位数三位数直接计算即可。
LR棋盘
应得:40 实得:35
题意:读入一个字符串,在串上有LR两种标记,L只能向左走,R只能向右走,每次只能走一个L或R,只能向没东西的格子走,问有多少种走法。最后对1e9+7取模
数据:对于40%,len∈[1,10],棋子数∈[1,5];
对于100%,len属于[1,20000],棋子数∈ [1,2000]
看到题后觉得要么是dp,要么是排列组合,因为要取模,不可能有暴力求解。
dp[i]定义为从1到i空有几种方法,但是这样就很难计算,因为LR可以移动到i的外面。
从另一个角度思考,因为LR放在一起时会变成一个独立的区间,那么可以单独处理最后相加,这样dp[i]就是1到第i个符号所有的方案数,只要再记录一下每个LR的区间即可
#include<bits/stdc++.h>#define Mod 1000000007#define M 200005using namespace std;char str[M];int L[M],R[M],dp[M];int main(){ scanf("%s",str); int n=strlen(str); int cnt=0; for(int i=0;i<n;i++) if(str[i]=='L')cnt++,L[cnt]=0,R[cnt]=i; else if(str[i]=='R')cnt++,L[cnt]=i,R[cnt]=n-1; //记录LR的位置 dp[0]=1; for(int i=0;i<n;i++) for(int j=cnt;j>=1;j--) if(L[j]<=i&&i<=R[j])//若满足i在这段区间内就加 dp[j]+=dp[j-1],dp[j]%=Mod; printf("%d\n",dp[cnt]); return 0;}
这个和之前有一道基因补全很像,那道是往一个序列里放数,这道题也可以这么想,只要保证他们的相对位置不变即可。
道路评价
应得:60 实得:40
题意:在一棵树上求任意两点见路径上最大值减最小值的差的和
数据:对于60%,n∈[1,5000];
对于100%,n属于[1,100000],边权∈[1,100000]
第一点,边权这么大,肯定要用long long才行
第二点,5000^2可以开一下,及吧每一个点都向其他点走一遍,dfs里多传最大最小值就行了,这样应该60,我却只有40。然后我把max,min改成if后就60了。
第三点,考试时想到一个方法,我们只需要求每一条边作为最大路径,最小路径出现的次数即可,但是朴素的方法求很慢,每一条边求一次就要n,最后依旧是n^2,没有区别。正解也是这样写的,但是再求边的使用数量上用并查集写。先将边排个序,从小到大,每次先求最大的,然后把这条边两边的点合并成一个点计算。正确性在于排序后下次访问的边肯定比之前的边要短,那么可以直接使用。这是对于求最小边,最大边反一下即可。
以下是图示
#include<bits/stdc++.h>#define M 100005using namespace std;struct node{int x,y,z;}A[M];bool cmp(node x,node y){return x.z>y.z;}int fa[M],cnt[M];//fa[]是父亲节点,cnt是求合并后这个点代表着几个点int Find(int x){return x==fa[x]?x:fa[x]=Find(fa[x]);}int main(){ int n; scanf("%d",&n); for(int i=1;i<n;i++)scanf("%d%d%d",&A[i].x,&A[i].y,&A[i].z); sort(A+1,A+n,cmp);//按边权从小到大 for(int i=1;i<=n;i++)fa[i]=i,cnt[i]=1;//初始化 long long Max=0,Min=0; for(int i=1;i<n;i++){ int x=Find(A[i].x),y=Find(A[i].y); Min+=(1LL)*A[i].z*cnt[x]*cnt[y]; fa[x]=y; cnt[y]+=cnt[x]; } for(int i=1;i<=n;i++)fa[i]=i,cnt[i]=1; for(int i=n-1;i>=1;i--){//循环反过来,避免一次排序 int x=Find(A[i].x),y=Find(A[i].y); Max+=(1LL)*A[i].z*cnt[x]*cnt[y]; fa[x]=y; cnt[y]+=cnt[x]; } printf("%lld\n",Max-Min); return 0;}
这样就可以n logn完成
- 10.3离线赛
- 10.26离线赛题解
- 天池离线赛
- 天池离线赛
- 天池离线赛
- 天池离线赛
- 10.4离线赛
- 离线赛20171004总结
- 10.6离线赛
- 离线赛20171006总结
- 20171006离线赛总结
- 20171007离线赛总结
- 离线赛20171007总结
- 10.7离线赛
- 10.8离线赛
- 离线赛20171008总结
- 离线赛20171008总结
- 离线赛总结
- 普通程序员如何转型深度学习?
- 堆排序
- uCOS任务堆栈的深入分析
- LEP与负载均衡—— 以PCDUINO实际案例来使用LEP提高网络带宽
- nginx配置url重写
- 10.3离线赛
- 生活中常见的电器,他们的工作原理你知道吗?
- 树状数组模板
- java实现图片裁剪
- Object Detection R-CNN
- Spring Cache抽象-使用Java类注解的方式整合EhCache
- Cocos2d-x游戏开发环境搭建
- 科普 | “开放知识”的定义
- c#实现图片裁剪