写在前面的一些话

如果我NOIP没退役,这大概会写成一个系列吧,所以这算是系列的开始,要写一些奇怪的东西?

首先解释下什么叫“拔钉子”,其实就是在钉子上做题嘛......至于钉子具体是个什么东西就当面或者QQ问我好了=。=

然后如果写成系列的话前面这些应该都是POI了,那就说说POI好了。我个人还是很喜欢POI的出题风格的,基本上没有什么 Phantasm码农题/仙人板板板子题/很超巨大无比数据结构题(这都是什么啊喂(#`O′) )。思路在解题中比较重要,然后细节有时候也比较需要注意,至于码力这个东西在哪里都可以练......总的来说整体水平可以接受(至少有很多题是我这个马上NOIP退役的蒟蒻能做的),有一点就是经常出现智商题(2333)。当然也有一些很神仙的可能高于省选水平(?)的题,不过看到了可以绕着走就是了,反正只要有NOIP的水平应该都能找到一些可写的题的=。=

然后POI一年好像有17道题,似乎是一年考好几次试总起来的。国内的各个OJ基本上能覆盖掉POI 2016及以前的题,所以这些题在网上或多或少都能找到题解,之前应该也有好多dalao都按年份刷过POI的。不过不知道为什么POI2017只有BZOJ上Claris搬的五道题,剩下的国内OJ好像都没有......(但是为什么有POI2018的啊,钉子上都没有啊=。=)

好了,废话也说够了,开始写我的解题吧=。=

Round I

Flappy Bird

这题和 NOIP 2014 飞扬的小鸟 没有什么关系......

因为这只鸟只要擦过最后一对柱子就可以了,所以我们正着扫一遍,对每个柱子用它和上个柱子的间隔维护小鸟可以飞到的上下边界(上界是用来判无解的),然后这样一路维护到最后得到一个下界$minh$,答案就是$\left\lfloor \frac{x[n]+minh}{2} \right\rfloor$(点一下相当于可以飞两格,可以自己画画)。注意小鸟能飞到的点的横纵坐标之和一定是偶数,这个也需要维护一下=。=

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 long long n,x,t1,t2,t3,up,down,len,last;
 6 int main ()
 7 {
 8     scanf("%lld%lld",&n,&x);
 9     for(int i=1;i<=n;i++)
10     {
11         scanf("%lld%lld%lld",&t1,&t2,&t3),len=t1-last;
12         down=max(down-len,t2+1),up=min(up+len,t3-1);
13         if((up-t1)&1) up--; if((down-t1)&1) down++;
14         if(up<down) printf("NIE\n"),exit(0); last=t1;
15     }
16     printf("%lld",(down+last)/2);
17     return 0;
18 }

View Code

Divisibility

首先有一个性质(其实我们小学可能都学过,雾):在B进制下一个数是B-1的倍数当且仅当其数位和是B-1的倍数

那么就很好做了,构造方法就是把所有数从大到小接起来,然后如果现在这个数不能整除被B-1整除就扣掉那个余数一位,这样剩余位数是最多的,数就是最大的,然后每个询问lower_bound一下就好了,注意边边角角的细节=。=

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=1000005;
 6 long long b,q,k,res,tot,bit;
 7 long long cnt[N];
 8 int main ()
 9 {
10     scanf("%lld%lld",&b,&q);
11     for(int i=0;i<b;i++)
12     {
13         scanf("%lld",&cnt[i]);
14         tot+=cnt[i]*i,bit+=cnt[i];
15     }
16     res=tot%(b-1);
17     if(res) cnt[res]--,bit--;
18     for(int i=1;i<b;i++)
19         cnt[i]+=cnt[i-1];
20     while(q--)
21     {
22         scanf("%lld",&k),k++;
23         long long pos=lower_bound(cnt,cnt+b,k)-cnt;
24         k<=cnt[b-1]?printf("%lld\n",pos):printf("-1\n");
25     }
26     return 0;
27 }

View Code

Difference Representations

出现了,智商题!

虽然这题非常CF,不太像OI题=。=

发现这个数列每隔两个元素翻一番,所以一会就超过1e9(询问的最大值)了。那么我们暴力预处理前面的数直到它加爆1e9(注意一定是加爆才行),这说明奇数下标的元素和前面那个数的差值已经爆掉1e9了,那么再能凑出来一定是一个偶数下标的元素减去它前面那个元素。

先把预处理的数塞进map里,然后把预处理得到的所有数对的较大下标塞进一个数组$mem$里;对于每个询问先尝试在map里查一下,查不到就在$mem$里面二分出第一个小于它的位置$pos$,这样$pos$前面的都会被凑出来,而后面的就要两个两个每次加$1$来凑,所以设预处理出last个数后爆掉1e9了,那么对于一个数$x$的答案就是$(last+2*(x-pos),last+2*(x-pos)-1)$

 1 #include<map>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<utility>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=1e7+7,MAXX=1e9;
 8 map<int,pair<int,int> > mp;
 9 map<int,pair<int,int> >::iterator it;
10 int a[100],mem[N],T,p,rd;
11 void prework()
12 {
13     a[1]=1,a[p=2]=2,mp[1]=make_pair(2,1);
14     while(a[p]<=MAXX||p%2==1)
15     {
16         if((++p)&1) a[p]=2*a[p-1];
17         else
18             for(int i=1;i<=a[p-1];i++)
19                 if(mp.find(i)==mp.end())
20                     {a[p]=a[p-1]+i; break;}
21         for(int i=1;i<p;i++)
22             mp[a[p]-a[i]]=make_pair(p,i);
23     }
24     for(it=mp.begin();it!=mp.end();it++)
25     {
26         pair<int,pair<int,int> > pr=*it;
27         mem[++mem[0]]=pr.first;
28     }
29 }
30 int main ()
31 {
32     prework(),scanf("%d",&T);
33     while(T--)
34     {
35         scanf("%d",&rd),it=mp.find(rd);
36         if(it!=mp.end())
37         {
38             pair<int,pair<int,int> > pr=*it;
39             printf("%d %d\n",pr.second.first,pr.second.second);
40         }
41         else
42         {
43             int    pre=lower_bound(mem+1,mem+1+mem[0],rd)-mem-1;
44             printf("%d %d\n",p+2*(rd-pre),p+2*(rd-pre)-1);
45         }
46     }
47     return 0;
48 }

View Code

Sabotage

友善的二分答案+树形DP检验

好像挺简单的,设$dp[i]$表示最坏情况下$i$的子树里有几个叛徒,然后每次二分完DP一下就好了(雾

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=500005;
 7 const double eps=1e-6;
 8 vector<int> son[N];
 9 int dp[N],siz[N];
10 int n,k,rd,cnt;
11 double l,r,mid;
12 void DFS1(int nde)
13 {
14     siz[nde]=1;
15     for(int i=0;i<(int)son[nde].size();i++)
16     {
17         int goal=son[nde][i]; DFS1(goal);
18         siz[nde]+=siz[goal];
19     }
20 }
21 void DFS2(int nde)
22 {
23     if(son[nde].empty())
24         {dp[nde]=1; return;}
25     int maxx=0;
26     for(int i=0;i<(int)son[nde].size();i++)
27     {
28         int goal=son[nde][i]; DFS2(goal);
29         maxx=max(maxx,dp[goal]);
30     }
31     dp[nde]=((double)maxx/(double)(siz[nde]-1)>mid)?siz[nde]:maxx;
32 }
33 bool check()
34 {
35     memset(dp,0,sizeof dp),DFS2(1);
36     return dp[1]<=k;
37 }
38 int main()
39 {
40     scanf("%d%d",&n,&k);
41     for(int i=2;i<=n;i++)
42     {
43         scanf("%d",&rd);
44         son[rd].push_back(i);
45     }
46     l=0,r=1,DFS1(1);
47     while(r-l>eps)
48     {
49         mid=(l+r)/2;
50         check()?r=mid:l=mid;
51     }
52     printf("%lf",r);
53     return 0;
54 }

View Code

Tourist

画风突变,做不来,告辞

求竞赛图的哈密顿回路,反正我是弃了,哪位神仙会做一定让我%1%

放个学长的链接吧=。=

Round 2

Sports competition

求一类特殊的二分图匹配的新思路(i207M说lyd讲过,我怎么不记得怕不是当时在摸鱼)

我们将每个左部点连到的右部点互相连起来并记录度数(只有一个右部点就连自己,度数加2),然后就得到了一个基环树森林。那么无解就是因为一棵基环树里的度数超过了点数的二倍,说明这个联通块里的边不够分了。判完无解之后我们就尝试把每棵基环树上的边定向来得到外向基环树,如果可行说明有唯一解;具体来说就是看看每个联通块里都有没有自环,如果有那么这棵基环树一定可以定向成一棵外向基环树,而没有的话就可能有两种定向,这样统计完如果有唯一解再DFS一遍即可得出方案。

 1 #include<cstdio>
 2 #include<vector>
 3 #include<cstring>
 4 #include<algorithm>
 5 using namespace std;
 6 const int N=1e6+6;
 7 const long long mod=1e9+7;
 8 int deg[N],sig[N],xnt[N],vis[N],cir[N],uni[N],outp[N];
 9 int p[N],noww[2*N],goal[2*N],val[2*N];
10 int n,t1,t2,pw,cnt,tot;
11 vector<int> col[N];
12 char rd[5];
13 void link(int f,int t,int v)
14 {
15     noww[++cnt]=p[f],p[f]=cnt;
16     goal[cnt]=t,val[cnt]=v;
17 }
18 long long qpow(long long x,long long k)
19 {
20     if(k==1) return x;
21     long long tmp=qpow(x,k/2);
22     return k%2?tmp*tmp%mod*x%mod:tmp*tmp%mod;
23 }
24 void DFS(int nde,int fth)
25 {
26     if(sig[nde]) uni[tot]=true;
27     vis[nde]=true,col[tot].push_back(nde);
28     for(int i=p[nde];i;i=noww[i])
29         if(goal[i]!=fth)
30         {
31             if(vis[goal[i]]) cir[tot]=goal[i];
32             else DFS(goal[i],nde);
33         }
34 }
35 void mark(int nde,int fth)
36 {
37     vis[nde]=true;
38     for(int i=p[nde];i;i=noww[i])
39         if(goal[i]!=fth)
40         {
41             outp[val[i]]=goal[i];
42             if(!vis[goal[i]]) mark(goal[i],nde);
43         }
44 }
45 int main()
46 {
47     scanf("%d",&n);
48     for(int i=1;i<=n;i++)
49     {
50         scanf("%s",rd);
51         if(rd[0]=='T')
52         {
53             scanf("%d",&t1),sig[t1]=true;
54             link(t1,t1,i),deg[t1]+=2;
55         }
56         else
57         {
58             scanf("%d%d",&t1,&t2);
59             link(t1,t2,i),link(t2,t1,i);
60             deg[t1]++,deg[t2]++;
61         }
62     }
63     for(int i=1;i<=n;i++)
64         if(!vis[i]) tot++,DFS(i,-1);
65     for(int i=1;i<=tot;i++)
66         for(int j=0;j<(int)col[i].size();j++)
67             xnt[i]+=deg[col[i][j]];
68     for(int i=1;i<=tot;i++)
69     {
70         if(xnt[i]>2*(int)col[i].size())
71             printf("NIE\n0"),exit(0);
72         if(!uni[i]) pw++;
73     }
74     if(pw) printf("NIE\n%lld",qpow(2,pw)),exit(0);
75     memset(vis,0,sizeof vis);
76     for(int i=1;i<=tot;i++)
77         mark(cir[i],-1);
78     printf("TAK\n");
79     for(int i=1;i<=n;i++)
80         printf("%d\n",outp[i]);
81     return 0;
82 }

View Code

Sum of digits

惊了,CF怕不是出了个POI原题弱化版

这就是CF1070A Find a number的加强版,现在询问数位和为$s$且能被$d$整除的第$k$小数(原题询问最小的数),当然数据范围也减少了不少

然后我咕了,做法应该差不多吧

Strike

又出现了,智商题!

一开始把题想复杂了,问ztb他说可以用线段树维护BFS序(不过这也算学到了,我以前从没想过这种东西233),结果后来又发现好像维护不了。然后i207M说他要写写试试,过了一会他告诉我他A了,根本不用线段树,直接模拟即可=。=

对每个点记录它是否存在和它有几个儿子还存在,然后记录当前点数和边数按题意模拟即可,每次答案即点数-边数,注意根节点特殊考虑一下

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 const int N=500005;
 6 int exi[N],anc[N],son[N];
 7 int p[N],noww[2*N],goal[2*N];
 8 int n,T,t1,t2,rd,cnt,cnn,cne,root;
 9 void link(int f,int t)
10 {
11     noww[++cnt]=p[f];
12     goal[cnt]=t,p[f]=cnt;
13 }
14 void DFS(int nde,int fth)
15 {
16     anc[nde]=fth,exi[nde]=true;
17     for(int i=p[nde];i;i=noww[i])
18         if(goal[i]!=fth) DFS(goal[i],nde),son[nde]++;
19 }
20 int main ()
21 {
22     scanf("%d",&n);
23     for(int i=1;i<n;i++)
24     {
25         scanf("%d%d",&t1,&t2);
26         link(t1,t2),link(t2,t1);
27     }
28     cnn=n,cne=n-1,root=1;
29     DFS(1,0),scanf("%d",&T);
30     while(T--)
31     {
32         scanf("%d",&rd);
33         if(rd>0)
34         {
35             exi[rd]=false,cnn--,cne-=son[rd];
36             if(rd!=root)
37             {
38                 son[anc[rd]]--;
39                 if(exi[anc[rd]]) cne--;
40             }
41         }
42         else
43         {
44             rd=-rd;
45             exi[rd]=true,cnn++,cne+=son[rd];
46             if(rd!=root)
47             {
48                 son[anc[rd]]++;
49                 if(exi[anc[rd]]) cne++;
50             }
51         }
52         printf("%d\n",cnn-cne);
53     }
54     return 0;
55 }

View Code

Shipping containers

纪念在钉子上的第一个Unaccepted(Runtime Error),因为没判断越界的问题=。=

根号分类讨论来均摊复杂度,对于距离$d$小于$sqrt(n)$的以$d$为间隔差分一下最后求前缀和,对于距离大于$sprt(n)$的直接暴力做,总复杂度$O(n$ $sqrt(n))$。注意空间可能比较紧,可以把标准调的小于根号$n$一些(钉子是按点测试而且大测试点基本都有3~4s,所以基本不会卡常)

 1 #pragma GCC optimize(2)
 2 #include<cmath>
 3 #include<cstdio>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 const int N=100005,Sqrt=290;
 8 int dif[Sqrt][N],num[N];
 9 int n,m,t1,t2,t3,ed,blo;
10 int main ()
11 {
12     scanf("%d%d",&n,&m),blo=min(288,(int)sqrt(n));
13     for(int i=1;i<=m;i++)
14     {
15         scanf("%d%d%d",&t1,&t2,&t3),ed=t1+(t2-1)*t3;
16         if(t3<=blo)
17         {
18             dif[t3][t1]++;
19             if(ed+t3<=n) dif[t3][ed+t3]--;
20         }
21         else
22             for(int i=t1;i<=ed;i+=t3) num[i]++;
23     }
24     for(int i=1;i<=blo;i++)
25         for(int j=1;j<=n;j++)
26         {
27             if(j-i>=0)
28                 dif[i][j]+=dif[i][j-i];
29             num[j]+=dif[i][j];
30         }
31     for(int i=1;i<=n;i++)
32         printf("%d ",num[i]);
33     return 0;
34 }

View Code

Pizza delivery


哇蒟蒻博主发现自己并没有按年份刷的实力和时间,于是......

咕咕咕飞走

如果这只鶸NOIP没退役他大概会回来补的,这之前大概POI的解题还得散着写=。=

转载于:https://www.cnblogs.com/ydnhaha/p/9851945.html

yd的拔钉子之路之 POI 2017相关推荐

  1. 轮胎扎了“钉子”该怎么办?到底要不要拔掉?

    开车过程中听到轮胎与地面接触时有异常的声音, 一般情况下要么是轮胎花纹中卡了石头,或是被扎了钉子等尖锐物品.如果是石头,最好用硬一点的东西将其清除:如果是扎了钉子的话,那我们要不要拔出来呢?不拔的情况 ...

  2. 周星驰20年电影之路

    中文名: 周星驰  英文名: Stephen Chow  出生年月:1962年6月22日  ×××: 虎  出生地: 香港  籍贯: 上海  太阳星座: 巨蟹座  月亮星座: 水瓶座  身高: 174 ...

  3. 车路协同 智能路侧设备网络安全接入技术要求

    1 范围 本文件包含智能路侧设备网络安全接入技术要求,包括智能路侧设备连接要求.接入要求.证书管理要求. 本文件适用于智能路侧设备网络安全接入的设计与开发. 2 规范性引用文件 下列文件中的内容通过文 ...

  4. 崮云湖街道:“钉钉子”精神破译发展密码

    崮云湖街道:"钉钉子"精神破译发展密码 王敏 徐军刚 2014年,是崮云湖街道改革创新,勇于担当的关键一年.创新谷加速器开工,济南轻轨R1线启动,43亿元的投资在这里落户,48个重 ...

  5. 量化交易---我的量化交易之路---001

    一.我的投资之路 我是从2017开始接触基金.股票之类的.印象中,当时是买基金,然后买进去进去就亏了,然后后来就没有弄,再次开始交易之类的2020,就开始搞货币基金,股票,期权,美股,还有数字货币.. ...

  6. qduoj 140 题目6 142 ycb的ACM进阶之路

    题目6 发布时间: 2017年5月22日 14:30   最后更新: 2017年5月22日 14:33   时间限制: 1000ms   内存限制: 128M 描述 给n,m,k,求上述方程中( X1 ...

  7. 调研分析-全球与中国可拔插接线端子市场现状及未来发展趋势

    根据QYR(恒州博智)的统计及预测,2021年全球可拔插接线端子市场销售额达到了 亿美元,预计2028年将达到 亿美元,年复合增长率(CAGR)为 %(2022-2028).地区层面来看,中国市场在过 ...

  8. 赢鸡:2010年2月网络经典段子集锦

    1:人生就是一个茶几,我们都是一个个杯具,当和谐的阳光打在脸上,每一个杯具都笑开颜! 2:人生最重要的不是所在的位置,而是所朝的方向.同样是个B,你一路向北能变成NB,撞破南墙不回头,就只能当个SB ...

  9. vld不输出泄漏信息_光纤天线方案和泄漏电缆方案的比较

    在我公司还没有推出这套全新的光纤天线隧道专网无线通信覆盖系统之前,隧道的专网无线通信的覆盖主要是用泄漏电缆,因为隧道是一个狭长的通道,纵向很长,横向较窄,高度不高,而且需要在隧道中覆盖的无线通信频段有 ...

最新文章

  1. J.U.C系列(六)ForkJoin的使用
  2. leetcode-114. Flatten Binary Tree to Linked List
  3. pku773_Happy 2006
  4. vue 项目加载顺序_如何提高Vue项目首页的加载速度
  5. ❤️和广告说再见,将“沉浸式阅读”进行到底❤️
  6. Redis内存分配简单分析
  7. T-SQL数据类型的细微差别(四)
  8. mysql 镜像安装方法_MySql镜像安装
  9. 中的draw函数_哪一个热图函数更快?
  10. 斯坦福大学自然语言处理第四课“语言模型(Language Modeling)”
  11. U盘里面的文件夹变成文件也打不开文件的寻回方法
  12. 科技爱好者周刊(第 154 期):1982年的信息社会预言
  13. Typora 自定义皮肤
  14. python中len函数_len()函数以及Python中的示例
  15. Android 应用提示Detected problems with API问题
  16. java基础应用程序超市收银_超市收银程序(JAVA课程设计 2011)
  17. Mp3Player VS Diskman(1)
  18. 服务器系统巡检命令,服务器巡检命令
  19. 将复数python与实数运算_python怎么实现复数运算
  20. 4.SPSS24安装教程

热门文章

  1. (15)javaScript入门
  2. Unity3D学习笔记(十九):UGUI、Image、Text、Button
  3. Android开发:怎样把Android studio中的Library公布到Jcenter
  4. 重置outlook 2010
  5. Linux的磁盘管理
  6. Golang unsafe.Pointer指针
  7. leetcode算法题--最后一块石头的重量 II★
  8. leetcode算法题--大礼包
  9. Java反射之如何判断类或变量、方法的修饰符(Modifier解析)
  10. Elide 4.3.1 发布,雅虎开源的应用数据 API 搭建平台