COCICONTEST# 29.11.2014# 题解+总结
来源:互联网 发布:福禄克网络 dsx 8000 编辑:程序博客网 时间:2024/06/05 19:27
NOIP临近,刷刷题。
这场比赛下来明显觉得自己代码能力不够,比如第五题stogovi很明显的LCA,也想到是用LCA,然而并木有写出来,对模板的应用不够熟练。在思维方面不够严谨,比如第四题coci,没有意识到题目给的选手分数范围的意义,也可能是因为读题不够仔细吧。
在时间分配上还存在严重问题,前面的水题不能保证正确性,想错或者在某个地方手抽打错,在调试上花了很多时间以至于想后面的题时有一点慌。这也可能是因为码代码的速度不够快吧。
第一题:
打表模拟,水题一道。
#include <iostream>#include <cstdio>using namespace std;int num[105] ;char a ;int cnt[10] ;int main(){ num[49]=num[81]=num[65]=num[90]=1 ; num[50]=num[87]=num[83]=num[88]=2 ; num[51]=num[69]=num[68]=num[67]=3 ; num[52]=num[82]=num[70]=num[86]=num[53]=num[84]=num[71]=num[66]=4 ; num[54]=num[89]=num[72]=num[55]=num[85]=num[74]=num[77]=num[78]=5 ; num[56]=num[73]=num[75]=num[44]=6 ; num[57]=num[79]=num[76]=num[46]=7 ; num[48]=num[80]=num[59]=num[47]=num[45]=num[91]=num[39]=num[61]=num[93]=8 ; while(~scanf("%c",&a)) ++cnt[num[a]] ; for(int i=1;i<=8;++i) printf("%d\n",cnt[i]); return 0;}
第二题:
不说了,水题一道。
但蒟蒻在写代码的时候习惯不好,明明可以用while循环写的,却手抽用递归,爆栈不解释。
#include <iostream>#include <cstdio>#include <cstdlib>#define MAXN 100010using namespace std;int n ,m ,p ,a ,b ,next[MAXN] ,ans ;bool vis[MAXN] ;int main(){ scanf("%d%d%d",&n,&m,&p); for(int i=1;i<=n;++i) { scanf("%d%d",&a,&b); if(!next[b]) next[b]=a; } vis[p]=1; while(next[p]) { ++ans; p=next[p]; if(vis[p]) { ans=-1; break; } vis[p]=1; } printf("%d\n",ans); return 0;}
第三题:
模拟水题一道,但蒟蒻竟然分都不分 %>_<%
枚举每一列,寻找到最高位置。由于该建筑物的边框只会是连续的一段,所有最高位置就是边框的终点。比较它和前一列的高度,周长肯定要加上它俩的高度差以及这一列的宽度(就是
#include <iostream>#include <cstdio>#include <cstring>#define abs(a) ((a)>0?(a):-(a))#define MAXN 1000#define MAXM 10005using namespace std;int ans ,n ,l[MAXM] ,r[MAXM] ,h[MAXM] ,maxh[MAXM] ,tmp1 ,tmp2 ,tmp3 ;char map[MAXN+5][MAXN+5] ;int main(){ scanf("%d",&n); memset(map,'.',sizeof map); tmp1=MAXM ; for(int i=1;i<=n;++i) { scanf("%d%d%d",&l[i],&r[i],&h[i]); --r[i]; tmp1=min(tmp1,l[i]) ,tmp2=max(tmp2,r[i]) ; } for(int i=tmp1;i<=tmp2+1;++i) { for(int j=1;j<=n;++j) if(l[j]<=i&&i<=r[j]) maxh[i]=max(maxh[i],h[j]); ans+=abs(maxh[i]-maxh[i-1]); if(maxh[i]>0)++ans; int end=max(maxh[i],maxh[i-1]); if(maxh[i]<maxh[i-1]) for(int j=min(maxh[i],maxh[i-1]);j<=end;++j) map[j][i-1]='#'; else for(int j=min(maxh[i],maxh[i-1]);j<=end;++j) map[j][i]='#'; map[maxh[i]][i]='#'; tmp3=max(tmp3,maxh[i]); } printf("%d\n",ans); for(int i=tmp3;i>0;--i) { for(int j=tmp1;j<=tmp2;++j) printf("%c",map[i][j]); puts(""); } for(int j=tmp1;j<=tmp2;++j) printf("*"); puts(""); return 0;}
第四题:
题目大意:给你
蒟蒻一开始以为分数的范围并没有用,就用树状数组乱YY了一种方法wa了
若没有分数范围,那么两个人的排名都为
正解:令
#include <iostream>#include <cstdio>#define MAXN 500005#define MAXM 650using namespace std;int n ,a[MAXN] ,b[MAXN] ,ans ;int num[MAXM+5][MAXM+5] ,s[MAXM+5][MAXM+5] ;int solve(int x1,int y1,int x2,int y2){ if(x2<0||y2<0) return 0; int ans=num[x2][y2] ; if(y1>0) ans-=num[x2][y1-1]; if(x1>0) ans-=num[x1-1][y2] ; if(x1>0&&y1>0) ans+=num[x1-1][y1-1] ; return ans;}int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%d%d",&a[i],&b[i]); ++s[a[i]][b[i]] ; } for(int i=0;i<=MAXM;++i) for(int j=0;j<=MAXM;++j) { num[i][j]=s[i][j]; if(i>0) num[i][j]+=num[i-1][j]; if(j>0) num[i][j]+=num[i][j-1]; if(i>0&&j>0) num[i][j]-=num[i-1][j-1] ; } for(int i=1;i<=n;++i) { printf("%d ",solve(a[i]+1,b[i]+1,MAXM,MAXM)+1); ans=n-solve(0,0,a[i]-1,b[i]-1) ; if(a[i]==MAXM)ans-=s[0][b[i]]; if(b[i]==MAXM)ans-=s[a[i]][0]; printf("%d\n",ans); } return 0;}
第五题:
很明显的LCA。
如果是加入元素
而对于操作b,即弹出栈顶元素,
而对于操作c,就找它俩的最近公共祖先,输出祖先的长度即可。
#include <iostream>#include <cstdio>#define MAXN 300005#define MAXK 20using namespace std;int n ,fa[MAXN] ,f[MAXN][MAXK] ,v ,w ,size[MAXN] ;char word[5] ;void adjust(int &u,int d){ for(int j=MAXK-1;j>=0;--j) if(size[f[u][j]]>=d) u=f[u][j] ;}int lca(int u,int v){ if(size[u]<size[v]) swap(u,v); if(size[u]>size[v]) adjust(u,size[v]); if(u==v) return u; for(int j=MAXK-1;j>=0;--j) if(f[u][j]!=f[v][j]) u=f[u][j] ,v=f[v][j] ; return f[u][0] ;}int main(){ scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%s%d",word,&v); v=fa[v] ; fa[i]=v ; if(word[0]=='a') { fa[i]=i ; size[i]=size[v]+1 ; f[i][0]=v ; for(int j=1;j<MAXK;++j) f[i][j]=f[f[i][j-1]][j-1] ; } else if(word[0]=='b') { printf("%d\n",fa[i]); fa[i]=f[fa[i]][0] ; } else { scanf("%d",&w); w=fa[w] ; printf("%d\n",size[lca(v,w)]); } } return 0;}
第六题:
当时在考场上就想过将所有询问保存起来,然后所有卡车一起跑,处理卡车掉头的地方,每一次都对询问处理一次。然而蒟蒻却更新了所有的卡车,就发现还没爆搜跑得快,于是果断写暴力= =
正解:将每一辆卡车的掉头地点、时间以及方向存起来,按时间排序。对于一个询问,只需要处理一个卡车就行了。所以将这个询问放在掉头数小的那辆车上。更新跟它有询问的车就行了。
接下来分析时间复杂度。
若一辆卡车的掉头数超过了
若一辆卡车的掉头数少于了
这样均摊下来,时间复杂度为
#include <iostream>#include <cstdio>#include <algorithm>#include <map>#include <vector>#define abs(a) ((a)>0?(a):-(a))#define MAXN 100005#define MAXK 300005#define pii pair<int,int>#define LL long long intusing namespace std;map<pii,vector<int> >sameask;int n ,m ,a ,b ,pos1 ;int num[MAXN] ,dir[MAXN] ,ans[MAXN] ;LL ti ;struct Car{ int id ,pos ,dir ; LL t; bool operator < (const Car &a)const { if(t!=a.t)return t<a.t; return dir>a.dir; }}car[MAXK] ,truck[MAXN] ;struct node{ int id ,v ; node *next ;}edge[MAXN] ,*adj[MAXN] ,*code=edge ;int check_left(const Car &a,const Car &b,LL t,int dir){ if(b.dir==0&&t>=b.t)return 0; int apos=a.pos ,bpos=b.pos ; if(b.dir==0) apos+=(a.t-b.t)*(-dir); else bpos+=(a.t-b.t)*b.dir; if(apos<bpos) return 1; return -1;}int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) { scanf("%d%d",&num[i],&a); ti=0; for(int j=1;j<num[i];++j) { scanf("%d",&b); Car e={i,a,a<b?1:-1,ti}; if(j==1) truck[i]=e; else car[pos1++]=e; ti+=abs(a-b) ,a=b ; } Car e={i,a,0,ti}; car[pos1++]=e; } for(int i=0;i<m;++i) { scanf("%d%d",&a,&b); if(a>b)swap(a,b); sameask[pii(a,b)].push_back(i); if((int)sameask[pii(a,b)].size()>1)continue; if(num[a]>num[b])swap(a,b); code->v=b ,code->id=i ,code->next=adj[a] ; adj[a]=code ; ++code ; dir[i]=truck[a].pos<truck[b].pos?1:-1; } sort(car,car+pos1); int id ,temp ,dir1 ; for(int i=0;i<pos1;++i) { id=car[i].id ; ti=truck[id].t ,dir1=truck[id].dir ; truck[id]=car[i]; for(node *p=adj[id];p!=NULL;p=p->next) { temp=check_left(truck[id],truck[p->v],ti,dir1); ans[p->id]+=(dir[p->id]*temp==-1); dir[p->id]=temp; } } int res ; for(map<pii,vector<int> >::iterator p=sameask.begin();p!=sameask.end();p++) { res=ans[p->second[0]]; for(int i=1;i<p->second.size();++i) ans[p->second[i]]=res; } for(int i=0;i<m;++i) printf("%d\n",ans[i]); return 0;}
- COCICONTEST# 29.11.2014# 题解+总结
- acm题解总结(1)
- NOIP2013题解+总结
- codeforces round338 总结&&题解
- JZWC【Day1】题解&总结
- JZWC【Day2】题解&总结
- JZWC【Day3】题解&总结
- JZWC【Day4】题解&总结
- 1.17题解和总结
- 6.6题解总结
- noip2016 游记+总结+题解
- noip2015 游记+总结+题解
- 2014 Multi-University Training Contest 9 题解&&总结
- 【NOIP模拟】20140809 题解 & 总结
- 【NOIP模拟】20140812 题解 & 总结
- 【NOIP模拟】20140813 题解 & 总结
- 【NOIP模拟】20140814 题解 & 总结
- 【NOIP模拟】20140815 题解 & 总结
- CSS行高——line-height
- 策略模式
- sqlite数据库中常用的sql语句
- C++ 类 内存分布 虚函数 单继承 多继承
- BigDecimal.ZERO
- COCICONTEST# 29.11.2014# 题解+总结
- 递归函数时间复杂度分析
- nodejs小问题:[1]express不是内部或外部命令
- 原子变量(AtomicLong, AtomicInteger, AtomicReference)
- symmetric_difference
- COCI2014 dom
- LeetCode 160 Intersection of Two Linked Lists
- OpenCV 2.4.10 + VS2010 开发环境配置
- Pop–实现任意iOS对象的任意属性的动态变化