20170725考试总结
来源:互联网 发布:原生js 双向绑定 编辑:程序博客网 时间:2024/06/10 18:08
第一题:膜拜AZUI
题目描述
一天,小A给了J·G一道水题,J·G一眼秒了,现在J·G想考考你们:
小A有N个灯,排成了一列,现在小A给出来一个叫做azui的奇葩操作,我们把开着的灯看作数字1,把关着的灯看作数字0,定义0 azui 0 = 1,0 azui 1 = 0,1 azui 1 = 1, 1 azui 0 = 0。现在小A有N个问题azui(l,r),表示询问从左往右的第l个灯向右一个一个azui到第r个灯的结果是什么。
输入
第1行一个整数N表示序列的长度。
第2行N个整数Ai,每个数不是0就是1,表示灯是关的还是开的。
第3行一个整数M表示询问的个数。
第4~M+3行,每行两个整数l和r,表示询问azui(l,r)。
输出
共M行,第i行回答第i个询问。
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
51 0 1 0 152 33 44 51 31 4
样例输出
00001
提示
对于30%的数据,N和M <= 5000
对于80%的数据,N和M <= 500000
对于100%的数据,N和M <= 1000000
题解:根据观察法azui运算是满足结合律和交换律,并且azui同一个数偶数次所得的值不变,所以只需要统计每一区间0和1的个数就可以算出答案。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>using namespace std;const int N=1000000+10;int T,n,l,r,a[N],now,sum[N];int azui(int x,bool flg){return (x==flg);}int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",&a[i]);sum[i]=sum[i-1]+a[i];}scanf("%d",&T);while(T--){scanf("%d %d",&l,&r);int tot1=sum[r]-sum[l];int tot2=r-l-tot1;now=a[l];if(tot1&1) now=azui(now,1);if(tot2&1) now=azui(now,0);printf("%d\n",now);}}
成绩:AC
分析:考试时还zz了一下,写了个树状数组认为自己很有道理的样子,然后考完发现自己想zz一样,明明不需要修改用个boll的树状数组O__O"…(幸好教师机跑得快让我水过去了~\(≧▽≦)/~啦啦啦)
第二题:小G的烦恼
题目描述
小G最近郁闷死了,MZ想考考他的智商,给了他一道题,但是小G退役了这么久,怎么可能做的出来啊?于是他跑去向quack大神求助,可是quack大神要打牌,于是找到了你,希望能够不让MZ失望。
问题是这样的:MZ想去全球各地旅行。原本是有两家航空公司可以选择的,但是现在那两家公司合并了。然而,在合并初期,两家还没有交接好,于是出现了两家都要收钱的问题。由于MZ只想出去玩一个月,她可以选择包月机票(两家公司都有),对于其中的一家公司A来说,只要花费X元,即可以在持有另一家公司的合法包月机票的情况下,乘坐任何票价不高于A公司定价的X元的飞机。另一家公司也是一样的。
简单来说,对于航线i有2种价格Pi和Qi,分别是A公司和B公司的定价。假设你持有X元的A公司月票和Y元的B公司月票,当Pi<=X并且Qi<=Y时,你才可以乘坐航线i。当然,如果单独购买这一趟航班的两张票也是可以的。
现在MZ告诉你了N-1个她想要去的城市,MZ初始时在1号位置,并且告诉了你所有航线的两个价格。想要知道,最小的花费。
输入
第1行2个整数N、M分别表示城市的个数,航线的条数。
第2-M+1行,每行4个整数ui,vi,Pi,Qi,分别表示航线的两个城市(飞机可以来回开),和两种价格。(可能存在重边和自环)
输出
共一行,一个整数ANS,表示最小的花费。
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
5 51 2 3 21 3 2 42 4 4 25 3 3 31 4 0 1
样例输出
7
提示
选择除了2-4的所有边,所以答案是3+4=7
【数据范围】
对于20%的数据N,M <= 15
对于50%的数据N <= 200, M <= 500
对于80%的数据N <= 500, M <= 1000
对于100%的数据N <= 2000, M <= 5000, Pi, Qi <= 10^9
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<ctime>using namespace std;const int N=2000+10;const int M=5000+10;const int inf=0x3f3f3f3f;struct node{int u,v,p,q;bool operator < (const node &a)const{return p<a.p;}}arr[M];int n,m,Q,fa[N];int root(int x){if(!fa[x]) return x;else return fa[x]=root(fa[x]);}void merge(int a,int b){fa[root(b)]=root(a);}int cal(){int res=-1,tot=0;memset(fa,0,sizeof fa);for(int i=1;i<=m&&tot<n;i++)if(arr[i].q<=Q){if(root(arr[i].u)!=root(arr[i].v)){merge(arr[i].u,arr[i].v);res=arr[i].p,tot++;}}if(res<0||tot<n-1) res=inf;return res;}int main(){scanf("%d %d",&n,&m);for(int i=1;i<=m;i++){scanf("%d %d",&arr[i].u,&arr[i].v);scanf("%d %d",&arr[i].p,&arr[i].q);}sort(arr+1,arr+m+1);int ans=inf;for(int i=1;i<=m;i++){Q=arr[i].q;ans=min(ans,Q+cal());}printf("%d\n",ans);}
成绩:80
分析:(⊙o⊙)…,考试时的思路是枚举p二分q时间复杂度正好卡在1s左右(然后成功被卡了下来)。
第三题:小Q的新玩具
题目描述
期末考试完了,小Q得到了一件套新玩具,总共有N个零件。
现在小Q想把新玩具搬回家里,可是他遇到了新的问题:
每个零件有自己的重量Wi,小Q要租车把它们带回家。车每次只能运总重量和小于Lim的玩具,按照其中最重的玩具的重量收费。
零件不能拆分成更小的部分。为了不打乱零件的顺序,增加自己拼装的难度,每次装车只能装连续的部分。
现在想请你帮助小Q计算把玩具全部搬回家的最小费用。
输入
第一行两个整数N和Limit。
接下来的N行,每行一个整数,代表第i个零件的重量。
输出
第一行一个数字,表示答案。
样例输入
(如果复制到控制台无换行,可以先粘贴到文本编辑器,再复制)
8 17 2 2 2 8 1 8 2 1
样例输出
12
提示
N<=300000
Wi小于int范围
题解:很明显的dp,方程式很白痴,dp[i]=min(dp[j]+max(j+1,j+2,....i))。如果提前处理max,那么是一个n^2的转移o(>﹏<)o,只有30分(hyh大佬暴力60属于特殊情况),那么需要dp优化,首先用单调队列维护递减的a[i]值,max的值就可以确定了,用set保存i之前的dp[j]+max,因为dp值一定不递减。当来了一个新的i时将a[i]插入单调队列,被弹出的元素set中对应的失效,而当前dp为set中的最小值或满足limit的情况下尽量靠前的dp值加上对列头。
#include<iostream>#include<cstdio>#include<cstring>#include<algorithm>#include<set>using namespace std;const int N=300000+10;const int inf=0x3f3f3f3f;struct node{long long val,num;int pos;node(){}node(long long a,long long b,int c){val=a,num=b,pos=c;}}q[N<<1];int n,head,tail;long long a[N],sum[N],L[N],dp[N],Limit;set<long long> Ans;int main(){scanf("%d %lld",&n,&Limit);for(int i=1;i<=n;i++){scanf("%lld",&a[i]);sum[i]=sum[i-1]+a[i];}for(int i=1;i<=n;i++){while(head<tail&&q[tail-1].num<=a[i])Ans.erase(q[tail-1].val),tail--;while(head<tail&&sum[i]-sum[q[head].pos]>Limit)Ans.erase(q[head+1].val),head++;if(head<tail){int val=dp[q[tail-1].pos]+a[i];q[tail++]=node(val,a[i],i);Ans.insert(val);}else q[tail++]=node(0,a[i],i);int best=lower_bound(sum,sum+n+1,sum[i]-Limit)-sum;dp[i]=dp[best]+q[head].num;if(!Ans.empty())dp[i]=min(dp[i],*Ans.begin());}printf("%lld\n",dp[n]);}
成绩:30
分析:标准暴力分/(ㄒoㄒ)/~~,考试时考虑过用线段树维护变化的dp[j]+max(新来一个a把前面的值更新。。)然后太复杂没有调出来%>_<%。
总结:(⊙o⊙)…,这次考得很正常,简单的分都拿到了,有一点难度的全丢了(尴尬),感觉dp优化很重要,连续3场作为第三题压轴,第二题生成树的思路其实很简单(然而考场上没想到,考完恍然大悟。。。。)第一题理解题意时花的时间有点长。。。QnQ
- 20170725考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 栈和队列
- DQN-《Human-level control through deep reinforcement learning》译文
- java多线程之等待换性机制简单使用
- L2-020. 功夫传人 BFS
- C
- 20170725考试总结
- 2017 Multi-University Training Contest
- 图解递归调用过程(Python)
- 初入JavaScript(待修改)
- C
- [kotlin系列] (s2_2)属性、字段、接口、可见性修饰
- 在Angular项目中使用PrimeNG组件
- dashboard windows 前端开发环境搭建
- addView()后子布局不居中问题总结与分析