2017.10.25考试总结
来源:互联网 发布:美发店收银软件 编辑:程序博客网 时间:2024/05/18 07:58
总结
其实这次考试的题目并不难,但是却考得比较崩。总结下原因有这么些:
- 思维不够缜密。这也是最重要的,想到非正解思路之后,还没有验证它的正确性,就开始打代码,导致浪费了大把的时间。
- 考试的策略问题。做题顺序的不当,导致了我第二题没拿到该拿的分,尤其需要注意调整,而且打对拍的也占用了较多的时间,三个半小时还是有点不太够用啊。
- 刷题不够,效率较低。我做思维题做的不算多,各个算法、数据结构的各个类型的题目也没有全部覆盖到,正因为刷题的缺少,导致解题思维没有成型,而且效率也比较低,错误比较多。
梦幻布丁(HNOI2009)
Problem Description
详细请戳链接! 偷个懒应该没人会发现吧
Thoughts
第一眼就是线段树,这不明摆着嘛,利用最长连续零的套路,维护左右区间的颜色状态(杂色/Ci色),还有区间最左边最右边的颜色,顺便计数即可。然而,这种轻轻松松就AC的想法还是too naive了。但因为
后来打完了,回来看这道题,发现可以优化,但是时间不够,开始打对拍。
我想的优化是,因为修改和查询都是对于全区间而言,那么颜色种类数k经过修改只可能变得更少,因为同种颜色必定会同时修改,不可能分为两种或多种颜色。而且既然线段树有较大的可能性要递归到最底层,那么就可以用zkw线段树优化,直接采用链式前向星的思想,修改特定颜色的时候,直接可以查询,并且把修改当做单点修改。
然后蒟蒻就想不到有什么比较好的优化方法了……然后在下考前几分钟草率地打了个对拍,拍了几百组就草率地交了。
期望得分:70 实际得分:50 考后,打了优化的思想,发现也是50分,数据一点梯度都没有啊喂
Solution
事实上,我从第一眼就被误导了,打线段树真个错误的决定。正解要用链表优化和启发式合并。
也就是,修改的时候,并不实际去进行修改,而是做标记,用nc[i]数组表示第i个现在是什么颜色,在读入的时候,就先处理出ans,修改时维护即可。在合并时,将元素较少的颜色合并到元素较多的颜色上。和题目中要求的反了?没关系,标记一下就好了。
Code
#include <iostream>#include <cstring>#include <cstdio>using namespace std;template <typename Tp> inline void read(Tp &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}const int size=1000010;int n,m,ans,c[size],nc[size],head[size],tail[size],nxt[size],cnt[size];void merge(int a,int b){ if(!cnt[a]) return ; cnt[b]+=cnt[a]; for(int i=head[a];~i;i=nxt[i]) { if(c[i-1]==b) ans--; if(c[i+1]==b) ans--; } for(int i=head[a];~i;i=nxt[i]) c[i]=b; nxt[tail[b]]=head[a];//接起来 tail[b]=tail[a]; head[a]=tail[a]=-1;//将a颜色清空 cnt[a]=0;}int main(){ freopen("pudding.in","r",stdin); freopen("pudding.out","w",stdout); int k,u,v; read(n),read(m); memset(head,-1,sizeof(head)); memset(tail,-1,sizeof(tail)); for(int i=1;i<=n;i++) { read(c[i]); nc[c[i]]=c[i]; if(c[i]!=c[i-1]) ans++; if(tail[c[i]]==-1) tail[c[i]]=i; cnt[c[i]]++; nxt[i]=head[c[i]]; head[c[i]]=i; } while(m--) { read(k); if(k==2) printf("%d\n",ans); else { read(u),read(v); if(u==v) continue; if(cnt[nc[u]]>cnt[nc[v]]) swap(nc[u],nc[v]); merge(nc[u],nc[v]); } } return 0;}
越狱(HNOI2008)
Problem Description
详细请戳链接! 再偷个懒应该还是没人会发现吧
Thoughts
考试的时候想复杂了,看了很久,觉得有点像组合数学+容斥原理,然后就需要知道连续两次的,减去连续三次,加上连续四次……但是这个常数不好推啊,我暴力+手推,推了两次公式,均被自己推翻。当时内心是崩溃的,而且心态又不是很好,因为先做了第三题(欲知有多惨,见下)……所以推了好久,没推出来,就去打对拍了,没救了,放弃治疗qwq
期望得分:0 实际得分:(已和谐)
Solution
事实上,第二题是最水的……看来只有我没有推出来,被各位神犇暴踩QAQ
考虑补集,首先所有方案是
Code
#include <iostream>#include <cstdio>using namespace std;typedef long long ll;const ll mod=100003;ll n,m;ll power(ll a,ll b){ ll res=1; while(b) { if(b&1) res=res*a%mod; a=a*a%mod; b>>=1; } return res;}int main(){ freopen("prison.in","r",stdin); freopen("prison.out","w",stdout); scanf("%lld%lld",&m,&n); printf("%lld\n",(power(m,n)+mod-(m*power(m-1,n-1)%mod))%mod); return 0;}
Problem
Problem Description
没找到原题,偷不了懒了……
Description
给你一张含有 n 个点 m 条边的联通无向图,记录 1 号点到每个点的最短路长度,询问
去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变,若不连通则也视为改
变。
Input
第一行两个正整数 n,m,
接下来 m 行,每行三个正整数数 i,j,k,表示一条边
Output
N 行,第 i 行表示去掉与 i 号相邻的所有边后,1 号点到多少个点的最短路长度改变。
Sample Input
2 1
1 2 1
Sample Output
1
1
Data Size
30% :
100% :
Thoughts
草率地看完题目后,我联想到了NOIP2013货车运输。刚开始的想法(错的!)是找一棵最小生成树,然后进行一次树形DP,找到每个节点的儿子节点并统计个数cnt,则删去该节点之后最短路径长发生改变的就是cnt。举了一个例子,挂了,发现当产生了有多条路径到x点均为最小权值时会挂,于是又做了各种麻烦的操作改……然而,打了一发对拍,惨烈地挂了。谁说最短路径的路径一定在最小生成树上的……
期望得分:0 实际得分:(已和谐)
Solution
正解需要先跑一边SPFA跑出单源最短路,然后再以每个点检查,找出作为最短路径的边,并重新建图,然后对于每一个删去的节点,bfs一下,查看能访问到多少节点,未访问到的就是改变的节点数。
这叫做建最短路图。貌似还是很有用的。
吐槽:重新建图超级麻烦,还要写两个不同的链式前向星,数组开到手抖
Code
#include <iostream>#include <cstring>#include <cstdio>#include <queue>using namespace std;template <typename Tp> inline void read(Tp &x){ x=0; char ch=getchar(); while(ch<'0'||ch>'9') ch=getchar(); while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();}const int maxn=5010,maxm=20010;int p,head[maxn],to[maxm<<1],w[maxm<<1],nxt[maxm<<1];int n,m,dis[maxn],que[maxn],p2,h2[maxn],t2[maxm<<1],n2[maxm<<1];bool inq[maxn],vis[maxn];queue<int> q;void insert(int u,int v,int tw){ to[++p]=v; w[p]=tw; nxt[p]=head[u]; head[u]=p;}void insert2(int u,int v){ t2[++p2]=v; n2[p2]=h2[u]; h2[u]=p2;}void input(){ int u,v,tw; read(n),read(m); for(int i=1;i<=m;i++) { read(u),read(v),read(tw); insert(u,v,tw);insert(v,u,tw); }}void spfa(){ int now; memset(dis,0x3f,sizeof(dis)); q.push(1); dis[1]=0;inq[1]=true; while(!q.empty()) { now=q.front(); q.pop(); inq[now]=false; for(int i=head[now];i;i=nxt[i]) if(dis[to[i]]>dis[now]+w[i]) { int v=to[i]; dis[v]=dis[now]+w[i]; if(!inq[v]) inq[v]=true,q.push(v); } } for(int i=1;i<=n;i++) { memset(vis,0,sizeof(vis)); for(int j=head[i];j;j=nxt[j]) { int v=to[j]; if(!vis[v]&&dis[v]==dis[i]+w[j]) vis[v]=true,insert2(i,v); } }}void work(int k){ int h=1,t=1,x,ans=0; memset(vis,0,sizeof(vis)); vis[1]=1;que[1]=1; while(h<=t) { x=que[h++]; for(int i=h2[x];i;i=n2[i]) if(!vis[t2[i]]&&t2[i]!=k) vis[t2[i]]=true,que[++t]=t2[i]; } for(int i=1;i<=n;i++) if(!vis[i]) ans++; printf("%d\n",ans);}int main(){ freopen("problem.in","r",stdin); freopen("problem.out","w",stdout); input(); spfa(); printf("%d\n",n-1); for(int i=2;i<=n;i++) work(i); return 0;}
- 2017.10.25考试总结
- 2017.3.25考试总结
- 本次考试总结(2017.10.5考试)
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 考试总结
- 图
- 蓝桥杯试题:加法变乘法
- PAT刷题:1016. Phone Bills (25)
- JAVA设计模式之单例模式
- Retrofit+RxJava+MVP模式使用
- 2017.10.25考试总结
- 掌柜大作战(7):Spring中配置定时任务,封装任务执行流程;同一时刻只让一台机器执行,尽可能避免并发和并行,避免任务数据被处理2次
- JVM启动参数详解(含调优)
- Linux系统关键文件备份脚本
- Ubuntu16.04搭建完全分布式hadoop-2.7.4
- C++ GUI Programming with Qt4 Second Edition 之 B.1 使用qmake
- 深度纸质学习与实验(三)-将TensorFlow加入kubernetes初试
- 反射_Field
- centos7 安装rlwrap