• [OI]Noip 2018 题解&总结(普及)


    考砸了,还有原谅我代码十分有限的可读性。

    一个人的真正伟大之处就在于他能够认识到自己的渺小。——保罗

    从一年前初一九月到现在18年10月接触OI已经有一年了。几次模拟赛也自我感觉良好,都过了一等的线,自己考试的心态当时也放的挺平。但也没想到会考出这么差的分数。

    于是乎今天来总结一下Noip 2018(普及组)的题目。希望自己能好好反思一下自己。

    Tips:民间数据分数分别来自:某不明dalao;洛谷;某中学数据


    初赛篇

    这是整个比赛当中出问题最严重的地方,自己在几次模拟赛中初赛成绩普遍偏低,当晚上知道自己算出来才64分的时候心里那个慌呀,等了一个星期得到消息自己是62分,刚刚好61分是GD分数线,很幸运的自己过了初赛。

    虽然初赛很水,但是自己真的得加强了,程序填空倒数第一题比倒数第二题还高几分,错误很zz,都是些没写Ans=***之类的问题。


    复赛篇

    去广州二中的路上非常ok,老师还给了我们棒棒糖和奶糖。几颗糖下肚,那份紧张感就完全消散了,在路上看看书,聊聊天,再玩下手机就到了地点。


    T1 标题统计


     

    T1 分析

    我们可以非常清晰地得出这是一道喷香的水题,但有人用了gets(),不清楚会不会WA,我用了getline().然后判断空格。

    民间数据分数:100;100;100

    Noip官方分数:100

    T1 程序

     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 龙虎斗


     

    T2 分析

    刚开始没开long long,令人着迷

    枚举每一个点放置是否更优,更优就更替。

    这道题不难,单纯模拟就可以做出来,需要注意的时要是双方势力相当时或 s2 放在哪里都不合适时要放在 m 点上。

    T2 程序

     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 程序

     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 }
    乱写的错解
     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 }
    dalao的正解

    T3 总结

    时间必须安排恰当,实在不行就舍弃。

    民间数据分数:10;10;10

    Noip官方分数:10


    T4 对称二叉树

    T4分析

    今年t4考的是图论,但貌似今年数据过水导致暴力+剪枝就能AC,这道题自己认为不能做%100数据于是自己就自动屏蔽其他数据,只去写满二叉树的部分(考完后才发现自己能写AC的代码,有点后悔),思路:找根节点,将给出的数据规划成一颗二叉树,最后枚举。

    T4 程序

     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 }
    自己的错解
     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取得自己理想的成绩!

  • 相关阅读:
    使用C#抓取网页内容并分析获取数据
    C#获取网页内容的三种方式
    jquery各种版本判断checkbox checked
    C#接口作为返回值
    Sql语句用string.Format格式化
    c# empty和null区别
    not is null 和 is not null
    每一个班级中每一门课程获得最高分的学生的学号
    hdu 2647
    hdu 3342
  • 原文地址:https://www.cnblogs.com/lihepei/p/9957619.html
Copyright © 2020-2023  润新知