NOIP2017

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NOIP2017相关的知识,希望对你有一定的参考价值。

期中考爆炸之后noip接着炸,怎么这么惨啊qwq。

Day 0

 像以前一样坐高铁,车上也没打什么代码,下午到广州。

然后就在酒店打了几个模版,也没怎么颓废。晚上写了cf教育场的ABC,D是一道组合数不会写,然后写了一下前几年pj的一些签到题(被回文日期虐哭QAQ),然后莫名熬到一点多才睡觉。

Day1

早早起床打了几个模版,都是1A,rp++。听说QZZ昨晚已经把教育场ABCDE都A了(吓哭)。

吃完早餐接着打模版,然后就一个上午过去了。中午大概睡了半小时,然后就坐地铁到广州六中。

QZZ:我五分钟AK!!!

拍了一下集体照,然后就找了一下试室,诶什么鬼我试室座位号108?

和初二zc在一个试室。

考前洗了把脸,清醒很多。

lz走过来:“不要紧张balabala。。”

我:“嗯....”。

我也惊讶自己一点都不紧张。。难道我心态有这么好?(不存在的...)

进试室,然后发现座位号是18QAQ,喝了口水,然后无所事事。。

啥?密码是啥?

蛤?怎么又错误?

蛤?怎么你们都知道密码?

蛤?怎么你们都开始看题了?

密码好几遍都听不清。。。

然后监考员拿张纸写着密码让我抄在草稿纸上。。

怎么还是开不了啊。。。

哦!没大写==(喷血.jpg)

然而已经过去5min了。。。

T1,诶这个好像要double,怎么办怎么办c++double我有点慌啊。。。

哦!10的整数倍。。(喷血.jpg*2)

T2,啊难道要字符串?哦,直接膜就可以了啊。。

T3,宽搜?好像不太难也不太容易。。

T4,x[i]单调递增,二分答案?怎么check啊我不会啊。。。

10min看完题开始码T1T2,没遇到什么障碍30min码完,大数据也过了(其实是目测过的)。。

然后不敢直接写T3,万一T1,T2出事就惨了啊。然后T2默默debug。。

好像没毛病?过!

然而此时已经15:30了。。感觉这速度有点慢了。。

T3,宽搜是肯定的,但是好像有点麻烦啊。

看见旁边2位大佬都打dfs。。。

诶,似乎可以按曼哈顿距离分类建边来spfa。。

但是不连续用膜法怎么处理啊QAQ。。

GDOI的时候也是这类题写spfa就写挂了啊。。

想来想去还是宽搜。。。

思路断断续续,很不清晰。。

怎么记录上一格颜色啊QAQ,多开一维的话好像就爆空间了啊。。(事实是我傻逼用错数组)

16:00了。。。不行不行一定要先写完。。

写到一半发现一个思路?

把白色格子当做一种颜色,走到白色格子花费为2,白色格子走到其他颜色格子花费为1,然后这样类似迷宫问题那样跑?

然后没有证明正确性就开始打了。

调来调去到16:40才过样例。。。大数据没过。。。

于是很快找出了反例。。。这时的心态可能有点崩了吧。。。(1=无望)

想到spfa的话似乎建边直接跑就行了啊,但是不知道自己还能不能调地出来。。T4还没有怎么看呢。。

只剩1h,我还能干什么?

想来想去还是放弃T3,自己写搜索的题真的太弱了,其实实力也不够。。

17:00,开始看T4。。

诶,这个check好像可以n^2的dp啊。。

开始写写写。。。

17:25,写完死活过不了样例。。。感觉是自己方程写错了,毕竟dp一直很差。。

那时头脑确实乱了。。。超级紧张,就是还剩5min数学最后一题还没写出来的那种紧张。。。

退而求其次,dfs!!!

17:30,dfs一直溢出。。。

没办法只能乱调了,然后用不正确的方法乱调过样例。。

17:40,停止码题。。。

查了查文件名和输入输出。。

隐约感觉后2题没分。。。

不想了,好好检查!

于是发现t2,t3都用了y_做变量名,记得曾经某场cf因为这样被卡成CE。。

改改改!!!直接复制到Word里面,Ctrl+F大法好!!!

反复查了几遍,比赛结束。。

走出考场天色已经黑了,心如死灰......

T3他们好像都写出来了呢。T4dp当然也有不少人写出来。

心情也没有和以往一样很不好,毕竟自己实力就这样嘛。。

吃饭的时候仔细回想自己的T4的DP,突然想到没过样例是因为自己默认把第1格当做起点了,还有f数组没有初始化。。。

细节啊!!!如果当时能冷静下来好好在T4 debug就好了,如果T3能冷静下来好好验证正确性就好了。

毕竟已经过去了,就这样吧。

回酒店打了一场Atcoder abc,然后t3都不会写。。信心--,rp--。。

然后颓废了一下,也是忘记几点回房间睡觉了。。

Day 2

回家!!!

然后昏睡一下午。。

晚上作业没心情补。。

总结

1.代码能力太差,一道题往往会调很久,最终无果......

2.写题不能乱写,思路错了还照着写会浪费很多时间,应该做到像LG那样写3题A 3题%%%

3.要敢于尝试,比如T3那样明明思路是对的,但就是太怂不敢写...

4.思想严重江化,定式思维,导致一些题大致思路出来但败在细节...

5.基础还是要巩固吧,毕竟搜索dp都总是写不好呢...

6.心态问题,不要总想着结果,考场上就只有你和题,用心把题写好,把分拿稳就足够了...

7.不能总是停留在想题,要多试着写写,写题速度要加快...

8.一道题调不过的时候要尝试换个思路或者把代码删掉重新写,有时候就是一些错的细节没有改正...

 

目标&计划

1.今年把两个坑填完...

2.不会的算法就学,然后可以渐渐尝试bzoj,算法要理解不能只是背模版...

3.不要看题解!!!不要看题解!!!不要看题解!!!

最多只能看别人的思路,不能对着别人代码调自己代码!!!

4.锻炼码力,多刷codeforces...希望在这一年能打上蓝名...

 

洛谷数据测了210,竟然有些心安,只因为T1,T2没炸。。

或许实力太弱只满足于此吧。。

最终也是100+100+10+0,没用的PJ二等滚粗......

 

初三了...... 有很多想说的话......

初中前2年oi都被自己荒废掉了......很可惜吧......

虽然有想好好努力的觉悟,但始终没有付出足够的时间和精力......

同届的机房oier也基本拿过1=了:qzz,cxk,csl,lg...qzz也是成功ak了呢...

虽然这次也是有一些因为失误考挂的,但他们也都具备了拿1=的实力。。

但感觉自己离1=的实力还是有点远呢......

文化课也是极差......期中裸考已经滚到年级100多......

成功沦为班里oi垫底+文化课垫底......

文化课也是要好好学啊......不能不复习考试啊......

那么,初三就争取把文化课搞好,同时有时间多打比赛多刷题吧......

至于也不要动不动就说要退役,oi的路还很长,不坚持到最后,又怎么知道自己一定做不到呢?

加油qwq......

附:NOIP2017题解

T1

技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <stack>
 7 #include <cmath>
 8 using namespace std;
 9 int a,b,c;
10 int ans=0;
11 int main()
12 {
13     freopen("score.in","r",stdin);
14     freopen("score.out","w",stdout);
15     scanf("%d%d%d",&a,&b,&c);
16     ans=(a*2+b*3+c*5)/10;
17     printf("%d",ans);
18     fclose(stdin); fclose(stdout);
19     return 0;
20 }
View Code

T2

 

技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <stack>
 7 #include <cmath>
 8 using namespace std;
 9 int n,q;
10 int a[1050];
11 int l,num;
12 int ans=0;
13 bool find(int x,int y)
14 {
15     int x2,k=1;
16     x2=x; int c=0;
17     while (x2>0) {
18       c=c+(x2%10)*k;
19       k=k*10;
20       x2=x2/10;
21       if (c==y) return true;
22       if (c>y) return false;
23     }
24     return false;
25 }
26 int main()
27 {
28     freopen("librarian.in","r",stdin);
29     freopen("librarian.out","w",stdout);
30     scanf("%d%d",&n,&q);
31     for (int i=1;i<=n;i++)
32       scanf("%d",&a[i]);
33     sort(a+1,a+n+1);
34     for (int i=1;i<=q;i++) {
35       scanf("%d%d",&l,&num);
36       ans=-1;
37       for (int j=n;j>=1;j--) {
38           if (a[j]<num) continue;
39         if (find(a[j],num)) ans=a[j];    
40     }
41       if (i!=q) printf("%d\n",ans);
42       if (i==q) printf("%d",ans);
43     }
44     fclose(stdin); fclose(stdout);
45     return 0;
46 }
View Code

 

T3

我写了spfa,按曼哈顿距离|x1-x2|+|y1-y2|分类建边;

曼哈顿距离为1,颜色相同边权为0,不同为1...

曼哈顿距离为2,颜色相同边权为2,不同为3...

然后跑一遍裸的spfa... 具体看代码...

 

技术分享图片
  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 #include <queue>
  6 #include <stack>
  7 #include <cmath>
  8 #define ll long long
  9 #define out(a) printf("%d",a)
 10 using namespace std;
 11 int n,m,fx,fy;
 12 int tot=0;
 13 bool f=false;
 14 int toit[100050],cost[100050],nexts[100050],list[100050],dis[100050],q[100050];
 15 bool flag[100050];
 16 int a[105][105],num[105][105];
 17 int dx[5]={0,0,0,1,-1};
 18 int dy[5]={0,1,-1,0,0};
 19 int read()
 20 {
 21     int s=0,t=1; char c;
 22     while (c<0||c>9){if (c==-) t=-1; c=getchar();}
 23     while (c>=0&&c<=9){s=s*10+c-0; c=getchar();}
 24     return s*t; 
 25 }
 26 bool check(int x,int y)
 27 {
 28     if (x<=0||x>m||y<=0||y>m) return false;
 29     return true;
 30 }
 31 void add(int a,int b,int c)
 32 {
 33     toit[++tot]=b;
 34     cost[tot]=c;
 35     nexts[tot]=list[a];
 36     list[a]=tot;
 37 }
 38 void QAQ()
 39 {
 40     if (a[m-1][m]>0) add(num[m-1][m],num[m][m],2);//,printf("%d %d %d\n",num[m-1][m],num[m][m],2);
 41     if (a[m][m-1]>0) add(num[m][m-1],num[m][m],2);//,printf("%d %d %d\n",num[m][m-1],num[m][m],2);
 42     if (a[m-1][m-1]>0) add(num[m-1][m-1],num[m][m],3);//,printf("%d %d %d\n",num[m-1][m-1],num[m][m],2);
 43 }
 44 void spfa(int s)
 45 {
 46     int v,k,head,tail;
 47     head=tail=1;
 48     memset(flag,true,sizeof(flag));
 49     memset(dis,127,sizeof(dis));
 50     q[1]=s; flag[s]=false; dis[s]=0;
 51     while (head<=tail) {
 52       v=q[head]; k=list[v];
 53       while (k!=0) {
 54       if (dis[v]+cost[k]<dis[toit[k]]) {
 55           dis[toit[k]]=dis[v]+cost[k];
 56           if (flag[toit[k]]) {
 57             flag[toit[k]]=false;
 58             q[++tail]=toit[k];
 59           } 
 60       }
 61       k=nexts[k];
 62     }
 63     flag[v]=true;
 64     head++;
 65   }
 66 }
 67 int main()
 68 {
 69     int x,y,z,xx,yy,xx_,yy_,cnt=0;
 70     m=read(); n=read(); 
 71     for (int i=1;i<=n;i++) {
 72         x=read(); y=read(); z=read();
 73         a[x][y]=z+1;
 74     }
 75     for (int i=1;i<=m;i++)
 76       for (int j=1;j<=m;j++)
 77         num[i][j]=++cnt;
 78     for (int i=1;i<=m;i++){
 79       for (int j=1;j<=m;j++) {
 80           if (a[i][j]>0) {
 81         for (int k=1;k<=4;k++) {
 82           xx=i+dx[k]; yy=j+dy[k];
 83           if (check(xx,yy)) {
 84               if (a[xx][yy]>0) {
 85               if (a[xx][yy]==a[i][j]) add(num[i][j],num[xx][yy],0);//,printf("%d %d %d\n",num[i][j],num[xx][yy],0);
 86             else add(num[i][j],num[xx][yy],1);//,printf("%d %d %d\n",num[i][j],num[xx][yy],1);
 87         }
 88         else {
 89           for (int u=1;u<=4;u++) {
 90               xx_=xx+dx[u]; yy_=yy+dy[u];
 91               if (check(xx_,yy_)&&a[xx_][yy_]>0) {
 92                     if (a[xx_][yy_]==a[i][j]) add(num[i][j],num[xx_][yy_],2);//,printf("%d %d %d\n",num[i][j],num[xx_][yy_],2);
 93             else add(num[i][j],num[xx_][yy_],3);//,printf("%d %d %d\n",num[i][j],num[xx_][yy_],3);
 94               }
 95             }
 96           }
 97       }
 98     }
 99   }
100   }
101 }
102   if (a[m][m]==0) QAQ();
103     spfa(1);
104     if (dis[m*m]==2139062143) out(-1);
105     else out(dis[m*m]);
106 }
View Code

 

T4

正解是二分+DP+单调队列优化...

由于自己不会单队优化看了很多篇博客和题解才大概会写...

f[i]=max(f[i],f[j]+s[i]);

f[j]是随i的右移而右移的,会重复枚举很多个f[j],所以可以用单调队列存下f[j]...

所以我们只要找的是max(f[j])...

 

对于格子j,如果j到i的距离>最大距离,就可以直接把它出队...

 

对于格子j,如果ji的距离>=最小距离,把f[j]与队尾比较,如果f[q[tail]]<f[j],那么f[q[tail]]也是可以直接出队...

因此维护的是一个单调递减队列,队头就是最大值就可以直接用...

记得判head<=tail,记得开ll!!!

技术分享图片
 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 #include <stack>
 7 #include <cmath>
 8 #define ll long long
 9 #define out(a) printf("%d",a)
10 using namespace std;
11 int n,d,k;
12 int x[500050],s[500050];
13 ll f[500050];
14 ll q[500050];
15 ll lbound,rbound,middle;
16 ll sum=0;
17 int read()
18 {
19     int s=0,t=1; char c;
20     while (c<0||c>9){if (c==-) t=-1; c=getchar();}
21     while (c>=0&&c<=9){s=s*10+c-0; c=getchar();}
22     return s*t;
23 }
24 ll getmin(ll x)
25 {
26     if (x>=d) return 1;
27     return d-x;
28 }
29 ll getmax(ll x)
30 {
31     return x+d;
32 }
33 ll check(ll m)
34 {
35     ll maxn=(ll)-1<<60;
36     int head,tail;
37     head=1; tail=0;
38     int now=0;
39     for (int i=1;i<=n;i++)
40       f[i]=(ll)-1<<60;
41     f[0]=0;
42     for (int i=1;i<=n;i++) {
43       while (x[now]+getmin(m)<=x[i]) {
44           while (head<=tail&&f[now]>f[q[tail]]) tail--;
45           q[++tail]=now;
46           now++;
47       }
48       while (head<=tail&&x[q[head]]+getmax(m)<x[i]) head++;
49       if (head<=tail) f[i]=f[q[head]]+s[i];
50   }
51   for (int i=0;i<=n;i++)
52     maxn=max(maxn,f[i]);
53     return maxn;
54 }
55 int main()
56 {
57     n=read(); d=read(); k=read();
58     for (int i=1;i<=n;i++) {
59       x[i]=read(),s[i]=read();
60       if (s[i]>0) sum=sum+s[i];
61     }
62       lbound=1; rbound=x[n];
63       if (sum<k) {
64           puts("-1");
65           return 0;
66       }
67     while (lbound<=rbound) {
68       middle=(lbound+rbound)>>1;
69       if (check(middle)>=k) rbound=middle-1;
70       else lbound=middle+1;
71       //printf("%d %d\n",middle,check(middle));
72     }
73     out(lbound);
74     return 0;
75 }
View Code

 


以上是关于NOIP2017的主要内容,如果未能解决你的问题,请参考以下文章

心情NOIP2017的感想

NOIP2017

NOIP模拟2017.6.11解题报告

Noip2017 感悟

NOIP2017系列——写在前面

noip2010普及组复赛接水问题