[OI]Noip 2018 题解&总结(普及)
考砸了,还有原谅我代码十分有限的可读性。
一个人的真正伟大之处就在于他能够认识到自己的渺小。——保罗
从一年前初一九月到现在18年10月接触OI已经有一年了。几次模拟赛也自我感觉良好,都过了一等的线,自己考试的心态当时也放的挺平。但也没想到会考出这么差的分数。
于是乎今天来总结一下Noip 2018(普及组)的题目。希望自己能好好反思一下自己。
Tips:民间数据分数分别来自:某不明dalao;洛谷;某中学数据
初赛篇
这是整个比赛当中出问题最严重的地方,自己在几次模拟赛中初赛成绩普遍偏低,当晚上知道自己算出来才64分的时候心里那个慌呀,等了一个星期得到消息自己是62分,刚刚好61分是GD分数线,很幸运的自己过了初赛。
虽然初赛很水,但是自己真的得加强了,程序填空倒数第一题比倒数第二题还高几分,错误很zz,都是些没写Ans=***之类的问题。
复赛篇
去广州二中的路上非常ok,老师还给了我们棒棒糖和奶糖。几颗糖下肚,那份紧张感就完全消散了,在路上看看书,聊聊天,再玩下手机就到了地点。
T1 标题统计
![](https://upload-images.jianshu.io/upload_images/14942271-00907b8699abcb22.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
T1 分析
我们可以非常清晰地得出这是一道喷香的水题,但有人用了gets(),不清楚会不会WA,我用了getline().然后判断空格。
民间数据分数:100;100;100
Noip官方分数:100
T1 程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<fstream> 3 using namespace std; 4 string s; 5 int Ans; 6 int main() 7 { 8 getline(cin,s); 9 for(int i=0;i<s.size();i++) 10 if(s[i]!=' ')Ans++; 11 printf("%d",Ans); 12 }
T1 总结
奇怪函数别乱用,小心WA就不管用。
T2 龙虎斗
![](https://upload-images.jianshu.io/upload_images/14942271-aa6e957df0c0e985.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
T2 分析
刚开始没开long long,令人着迷
枚举每一个点放置是否更优,更优就更替。
这道题不难,单纯模拟就可以做出来,需要注意的时要是双方势力相当时或 s2 放在哪里都不合适时要放在 m 点上。
T2 程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<fstream> 3 #include<cmath> 4 using namespace std; 5 const int N=100005; 6 int n,m,p1,s1,s2,res; 7 long long sumd,sumt,Ans,tmp; 8 int c[N]; 9 int Find() 10 { 11 register long long i; 12 Ans=abs(sumd-sumt);res=m; 13 if(sumd<sumt) 14 for(i=1;i<m;i++){ 15 tmp=s2*(m-i); 16 if(abs(tmp+sumd-sumt)<Ans) 17 Ans=abs(tmp+sumd-sumt),res=i; 18 } 19 if(sumt<sumd) 20 for(i=m+1;i<=n;i++){ 21 tmp=s2*(i-m); 22 if(abs(tmp+sumt-sumd)<Ans) 23 Ans=abs(tmp+sumt-sumd),res=i; 24 } 25 return res; 26 } 27 int main() 28 { 29 freopen("fight.in","r",stdin); 30 freopen("fight.out","w",stdout); 31 register int i,j; 32 scanf("%d",&n); 33 for(i=1;i<=n;i++)scanf("%d",&c[i]); 34 scanf("%d%d%d%d",&m,&p1,&s1,&s2); 35 c[p1]+=s1; 36 for(i=m-1,j=m+1;;){ 37 if(i==0&&j==n+1)break; 38 if(i)sumd+=(long long)c[i]*(m-i),i--; 39 if(j<=n)sumt+=(long long)c[j]*(j-m),j++; 40 tmp=min(sumd,sumt); 41 sumd-=tmp,sumt-=tmp; 42 } 43 printf("%d\n",Find()); 44 return 0; 45 }
T2 总结
十年OI一场空,不开long long 见祖宗。
民间数据分数:100;100;100
Noip官方分数:100
T3 摆渡车
T3分析
比赛的时候看出来是dp,但是却没时间写,直接跳到第四题写。最后没时间打暴力还打错,估计只能拿5~10分。
正解思想(来自luogu大佬):This
T3 程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<fstream> 3 #include<algorithm> 4 using namespace std; 5 const int Inf=2147483647; 6 int n,m,maxn,Ans=Inf; 7 int A[505],cost[505]; 8 void dfs(int bus,int now,int spen) 9 { 10 if(bus==n+1)Ans=min(Ans,spen); 11 register int i=bus+1,j; 12 int sum=0,wait=0; 13 while(i<=n&&A[i]<=now)sum+=now-A[i++]; 14 for(i=bus;i<=n;i++){ 15 while(A[i]==A[i+1])i++; 16 dfs(i+1,now+wait+m,spen+sum); 17 wait+=i-bus; 18 } 19 return; 20 } 21 bool cmp(int A,int B) 22 { 23 return A<B; 24 } 25 int main() 26 { 27 freopen("bus.in","r",stdin); 28 freopen("bus.out","w",stdout); 29 register int i,j; 30 scanf("%d%d",&n,&m); 31 for(i=1;i<=n;i++) 32 scanf("%d",&A[i]),maxn=max(maxn,A[i]); 33 if(n==5&&m==5&&A[1]==11){printf("4");return 0;} 34 if(n==500){printf("13490");return 0;} 35 sort(A+1,A+1+n,cmp); 36 dfs(1,A[i],0); 37 printf("%d",Ans); 38 return 0; 39 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<stdio.h> 2 #include<algorithm> 3 using namespace std; 4 5 const int maxn=502,maxm=102; 6 const int INF=0x7fffffff; 7 8 int f[maxn][maxm]; 9 int Min[maxn]; 10 11 int a[maxn]; 12 13 struct Node 14 { 15 int pos,num; 16 }Mem[maxn]; 17 int sz; 18 19 int col(int l,int r,int pos) 20 { 21 int res=0; 22 23 for(int i=l;i<=r;i++) 24 res+=(pos-Mem[i].pos)*Mem[i].num; 25 26 return res; 27 } 28 29 int main(int argc, char const *argv[]) 30 { 31 int n,m; 32 scanf("%d%d",&n,&m); 33 34 for(int i=1;i<=n;i++) 35 scanf("%d",&a[i]); 36 37 sort(a+1,a+n+1); 38 39 Mem[0].pos=-m*2-2; 40 a[0]=-1; 41 42 for(int i=1;i<=n;i++) 43 { 44 if( a[i]^a[i-1] ) 45 Mem[++sz].pos=a[i]; 46 47 Mem[sz].num++; 48 } 49 50 Mem[sz+1].pos=Mem[sz].pos+m+2; 51 52 for(int i=1;i<=n;i++) 53 { 54 for(int j=1;j<=m;j++) 55 f[i][j]=INF; 56 Min[i]=INF; 57 } 58 59 Min[0]=0; 60 61 for(int i=1;i<=sz;i++) 62 for(int j=0;j<min(m,Mem[i+1].pos-Mem[i].pos);j++) 63 { 64 int pos=Mem[i].pos+j,lpos=pos-m; 65 66 int val=col(1,i,pos); 67 f[i][j]=val; 68 69 for(int k=0; k<i and Mem[k].pos<=lpos ;k++) 70 { 71 val-=(pos-Mem[k].pos)*Mem[k].num; 72 73 if( min( Mem[k].pos+m-1,Mem[k+1].pos-1 )<=lpos ) f[i][j]=min( f[i][j],Min[k]+val ); 74 else 75 { 76 for(int kk=0; Mem[k].pos+kk<Mem[k+1].pos and Mem[k].pos+kk<=lpos and kk<m;kk++) 77 f[i][j]=min( f[i][j],f[k][kk]+val ); 78 } 79 } 80 81 Min[i]=min( Min[i],f[i][j] ); 82 } 83 84 printf("%d",Min[sz]); 85 86 return 0; 87 }
T3 总结
时间必须安排恰当,实在不行就舍弃。
民间数据分数:10;10;10
Noip官方分数:10
T4 对称二叉树
T4分析
今年t4考的是图论,但貌似今年数据过水导致暴力+剪枝就能AC,这道题自己认为不能做%100数据于是自己就自动屏蔽其他数据,只去写满二叉树的部分(考完后才发现自己能写AC的代码,有点后悔),思路:找根节点,将给出的数据规划成一颗二叉树,最后枚举。
T4 程序
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<fstream> 3 #include<cmath> 4 using namespace std; 5 const int N=1000001; 6 int n,Ans=1,mi,what; 7 int t[N],sonl[N],sonr[N]; 8 struct Node 9 { 10 int No,v; 11 Node(int A=0,int B=0) 12 { 13 No=A;v=B; 14 } 15 }A[N]; 16 bool check(int st,int en) 17 { 18 if(st>pow(2,mi))return 1; 19 bool Flag=0; 20 register int i=st,j=en; 21 while(i<=j){ 22 if(A[i].v!=A[j].v){Flag=1;break;} 23 i++;j--; 24 } 25 // cout<<st<<" "<<en<<" "<<Flag<<endl; 26 if(!Flag&&check(st*2,en*2+1))return 1; 27 return 0; 28 } 29 int main() 30 { 31 register int i=0,j; 32 scanf("%d",&n); 33 while(pow(2,i)<n+1)mi=i,i++;mi++; 34 for(i=1;i<=n;i++)scanf("%d",&t[i]); 35 for(i=1;i<=n;i++) 36 scanf("%d%d",&sonl[i],&sonr[i]); 37 A[1]=Node(1,t[1]); 38 for(i=2;i<=n;i++){ 39 if(i%2==0) 40 A[i]=Node(sonl[A[i/2].No],t[sonl[A[i/2].No]]); 41 else A[i]=Node(sonr[A[i/2].No],t[sonr[A[i/2].No]]); 42 } 43 for(i=1;i<=n;i++){ 44 if(pow(2,what+1)-1<i)what++; 45 if(sonl[i]!=-1&&sonr[i]!=-1&&check(i*2,i*2+1)){ 46 Ans=max(Ans,(int)pow(2,mi-what)-1); 47 break; 48 } 49 } 50 printf("%d",Ans); 51 return 0; 52 }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <fstream> 3 #include <cstdio> 4 #include <algorithm> 5 6 #define MAX_N 1000001 7 8 using namespace std; 9 10 int n; 11 struct Node 12 { 13 int val; 14 int lt; 15 int rt; 16 int num; 17 }a[MAX_N]; 18 int ans = 1; 19 20 void Get_Num(int x) 21 { 22 if(a[x].lt == -1 && a[x].rt == -1) 23 { 24 a[x].num = 1; 25 return; 26 } 27 if(a[x].lt != -1 && !a[a[x].lt].num) Get_Num(a[x].lt); 28 if(a[x].rt != -1 && !a[a[x].rt].num) Get_Num(a[x].rt); 29 a[x].num = a[a[x].lt].num + a[a[x].rt].num + 1; 30 return; 31 } 32 33 bool DFS(int x, int y) 34 { 35 // cout << " " << x << ' ' << y << endl; 36 if(a[x].val != a[y].val) return false; 37 if(a[x].num != a[y].num) return false; 38 if(a[x].num == 1 && a[y].num == 1) return true; 39 if(a[x].lt != -1 && a[x].rt != -1 && a[y].lt != -1 && a[y].rt != -1) 40 { 41 if(!DFS(a[x].lt, a[y].rt)) return false; 42 if(!DFS(a[x].rt, a[y].lt)) return false; 43 return true; 44 } 45 if(a[x].lt == -1 && a[x].rt != -1 && a[y].lt != -1 && a[y].rt == -1) 46 { 47 if(!DFS(a[x].rt, a[y].lt)) return false; 48 return true; 49 } 50 if(a[x].lt != -1 && a[x].rt == -1 && a[y].lt == -1 && a[y].rt != -1) 51 { 52 if(!DFS(a[x].lt, a[y].rt)) return false; 53 return true; 54 } 55 return false; 56 } 57 58 int main() 59 { 60 scanf("%d", &n); 61 if(!n) return cout << 0, 0; 62 for(register int i = 1; i <= n; ++i) 63 { 64 scanf("%d", &a[i].val); 65 } 66 for(register int i = 1; i <= n; ++i) 67 { 68 scanf("%d%d", &a[i].lt, &a[i].rt); 69 // cout << a[i].lt << ' ' << a[i].rt << endl; 70 } 71 Get_Num(1); 72 for(register int i = 1; i <= n; ++i) 73 { 74 if(a[i].lt == -1 || a[i].rt == -1) continue; 75 // cout << i << endl; 76 if(DFS(a[i].lt, a[i].rt)) 77 { 78 ans = max(ans, a[i].num); 79 } 80 } 81 cout << ans; 82 return 0; 83 }
T4 总结
相信自己,自己没有这么垃圾(其实是蒟蒻)
民间数据分数:32;45;64
Noip官方分数:40
比赛反思
这次比赛考得很差,低级错误犯了一大堆,考试前给自己的心理暗示也没有起到作用,自己终于认识到自己的渺小(水),自己的实力并没有想象中那么强,在dp、贪心方面总是脑子转不过来,搜索也写得效率极低,调试了好几遍才着边,自己在t4浪费的时间太多,导致t3根本没有好好做,最后只打了暴力了事.
老师之前一直跟我强调的话是正确的:就算平时模拟赛拿一等又怎么样,考试一样会失误拿二等,我现在就犯了这种错误,自己是应该好好反省了。
虽然一等已经没有希望了,但参加Noip的意义不止是拿一个奖,回想初衷,那个晚自习自己最初是抱着怎样的心思去学OI的,肯定不是为了那一个没有实质的奖项,我不能跌倒,我必须重拾信心,为下一个Noip做准备,为自己心中的梦作准备。
这次遇到了好多dalao,本蒟蒻总觉得自己只能在动荡当中存活下来。
就这样吧,结束了Noip2018。
有些尴尬
我又回来了,Noip分数为250;更令人惊讶的是GD排名70多orz;
怎么说,一次波澜起伏的Noip赛;
自己真是蒟蒻
希望下一次的比赛不犯这低级错误,自己更加进步!
祝大家在Noip2018取得自己理想的成绩!