写在前面的一些话

如果我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$(点一下相当于可以飞两格,可以自己画画)。注意小鸟能飞到的点的横纵坐标之和一定是偶数,这个也需要维护一下=。=

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
long long n,x,t1,t2,t3,up,down,len,last;
int main ()
{
scanf("%lld%lld",&n,&x);
for(int i=;i<=n;i++)
{
scanf("%lld%lld%lld",&t1,&t2,&t3),len=t1-last;
down=max(down-len,t2+),up=min(up+len,t3-);
if((up-t1)&) up--; if((down-t1)&) down++;
if(up<down) printf("NIE\n"),exit(); last=t1;
}
printf("%lld",(down+last)/);
return ;
}

Divisibility

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

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

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
long long b,q,k,res,tot,bit;
long long cnt[N];
int main ()
{
scanf("%lld%lld",&b,&q);
for(int i=;i<b;i++)
{
scanf("%lld",&cnt[i]);
tot+=cnt[i]*i,bit+=cnt[i];
}
res=tot%(b-);
if(res) cnt[res]--,bit--;
for(int i=;i<b;i++)
cnt[i]+=cnt[i-];
while(q--)
{
scanf("%lld",&k),k++;
long long pos=lower_bound(cnt,cnt+b,k)-cnt;
k<=cnt[b-]?printf("%lld\n",pos):printf("-1\n");
}
return ;
}

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)$

 #include<map>
#include<cstdio>
#include<cstring>
#include<utility>
#include<algorithm>
using namespace std;
const int N=1e7+,MAXX=1e9;
map<int,pair<int,int> > mp;
map<int,pair<int,int> >::iterator it;
int a[],mem[N],T,p,rd;
void prework()
{
a[]=,a[p=]=,mp[]=make_pair(,);
while(a[p]<=MAXX||p%==)
{
if((++p)&) a[p]=*a[p-];
else
for(int i=;i<=a[p-];i++)
if(mp.find(i)==mp.end())
{a[p]=a[p-]+i; break;}
for(int i=;i<p;i++)
mp[a[p]-a[i]]=make_pair(p,i);
}
for(it=mp.begin();it!=mp.end();it++)
{
pair<int,pair<int,int> > pr=*it;
mem[++mem[]]=pr.first;
}
}
int main ()
{
prework(),scanf("%d",&T);
while(T--)
{
scanf("%d",&rd),it=mp.find(rd);
if(it!=mp.end())
{
pair<int,pair<int,int> > pr=*it;
printf("%d %d\n",pr.second.first,pr.second.second);
}
else
{
int pre=lower_bound(mem+,mem++mem[],rd)-mem-;
printf("%d %d\n",p+*(rd-pre),p+*(rd-pre)-);
}
}
return ;
}

Sabotage

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

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

 #include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
const double eps=1e-;
vector<int> son[N];
int dp[N],siz[N];
int n,k,rd,cnt;
double l,r,mid;
void DFS1(int nde)
{
siz[nde]=;
for(int i=;i<(int)son[nde].size();i++)
{
int goal=son[nde][i]; DFS1(goal);
siz[nde]+=siz[goal];
}
}
void DFS2(int nde)
{
if(son[nde].empty())
{dp[nde]=; return;}
int maxx=;
for(int i=;i<(int)son[nde].size();i++)
{
int goal=son[nde][i]; DFS2(goal);
maxx=max(maxx,dp[goal]);
}
dp[nde]=((double)maxx/(double)(siz[nde]-)>mid)?siz[nde]:maxx;
}
bool check()
{
memset(dp,,sizeof dp),DFS2();
return dp[]<=k;
}
int main()
{
scanf("%d%d",&n,&k);
for(int i=;i<=n;i++)
{
scanf("%d",&rd);
son[rd].push_back(i);
}
l=,r=,DFS1();
while(r-l>eps)
{
mid=(l+r)/;
check()?r=mid:l=mid;
}
printf("%lf",r);
return ;
}

Tourist

画风突变,做不来,告辞

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

放个学长的链接吧=。=

Round 2

Sports competition

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

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

 #include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=1e6+;
const long long mod=1e9+;
int deg[N],sig[N],xnt[N],vis[N],cir[N],uni[N],outp[N];
int p[N],noww[*N],goal[*N],val[*N];
int n,t1,t2,pw,cnt,tot;
vector<int> col[N];
char rd[];
void link(int f,int t,int v)
{
noww[++cnt]=p[f],p[f]=cnt;
goal[cnt]=t,val[cnt]=v;
}
long long qpow(long long x,long long k)
{
if(k==) return x;
long long tmp=qpow(x,k/);
return k%?tmp*tmp%mod*x%mod:tmp*tmp%mod;
}
void DFS(int nde,int fth)
{
if(sig[nde]) uni[tot]=true;
vis[nde]=true,col[tot].push_back(nde);
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
if(vis[goal[i]]) cir[tot]=goal[i];
else DFS(goal[i],nde);
}
}
void mark(int nde,int fth)
{
vis[nde]=true;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth)
{
outp[val[i]]=goal[i];
if(!vis[goal[i]]) mark(goal[i],nde);
}
}
int main()
{
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%s",rd);
if(rd[]=='T')
{
scanf("%d",&t1),sig[t1]=true;
link(t1,t1,i),deg[t1]+=;
}
else
{
scanf("%d%d",&t1,&t2);
link(t1,t2,i),link(t2,t1,i);
deg[t1]++,deg[t2]++;
}
}
for(int i=;i<=n;i++)
if(!vis[i]) tot++,DFS(i,-);
for(int i=;i<=tot;i++)
for(int j=;j<(int)col[i].size();j++)
xnt[i]+=deg[col[i][j]];
for(int i=;i<=tot;i++)
{
if(xnt[i]>*(int)col[i].size())
printf("NIE\n0"),exit();
if(!uni[i]) pw++;
}
if(pw) printf("NIE\n%lld",qpow(,pw)),exit();
memset(vis,,sizeof vis);
for(int i=;i<=tot;i++)
mark(cir[i],-);
printf("TAK\n");
for(int i=;i<=n;i++)
printf("%d\n",outp[i]);
return ;
}

Sum of digits

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

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

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

Strike

又出现了,智商题!

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

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

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=;
int exi[N],anc[N],son[N];
int p[N],noww[*N],goal[*N];
int n,T,t1,t2,rd,cnt,cnn,cne,root;
void link(int f,int t)
{
noww[++cnt]=p[f];
goal[cnt]=t,p[f]=cnt;
}
void DFS(int nde,int fth)
{
anc[nde]=fth,exi[nde]=true;
for(int i=p[nde];i;i=noww[i])
if(goal[i]!=fth) DFS(goal[i],nde),son[nde]++;
}
int main ()
{
scanf("%d",&n);
for(int i=;i<n;i++)
{
scanf("%d%d",&t1,&t2);
link(t1,t2),link(t2,t1);
}
cnn=n,cne=n-,root=;
DFS(,),scanf("%d",&T);
while(T--)
{
scanf("%d",&rd);
if(rd>)
{
exi[rd]=false,cnn--,cne-=son[rd];
if(rd!=root)
{
son[anc[rd]]--;
if(exi[anc[rd]]) cne--;
}
}
else
{
rd=-rd;
exi[rd]=true,cnn++,cne+=son[rd];
if(rd!=root)
{
son[anc[rd]]++;
if(exi[anc[rd]]) cne++;
}
}
printf("%d\n",cnn-cne);
}
return ;
}

Shipping containers

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

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

 #pragma GCC optimize(2)
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=,Sqrt=;
int dif[Sqrt][N],num[N];
int n,m,t1,t2,t3,ed,blo;
int main ()
{
scanf("%d%d",&n,&m),blo=min(,(int)sqrt(n));
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&t1,&t2,&t3),ed=t1+(t2-)*t3;
if(t3<=blo)
{
dif[t3][t1]++;
if(ed+t3<=n) dif[t3][ed+t3]--;
}
else
for(int i=t1;i<=ed;i+=t3) num[i]++;
}
for(int i=;i<=blo;i++)
for(int j=;j<=n;j++)
{
if(j-i>=)
dif[i][j]+=dif[i][j-i];
num[j]+=dif[i][j];
}
for(int i=;i<=n;i++)
printf("%d ",num[i]);
return ;
}

Pizza delivery


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

咕咕咕飞走

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

yd的拔钉子之路之 POI 2017的更多相关文章

  1. BZOJ 4726 POI 2017 Sabota? 树形DP

    4726: [POI2017]Sabota? Time Limit: 20 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 128  Solved ...

  2. [ POI 2017 ] Sabota?

    Description 题目链接 Solution 因为一个节点染黑了子树就都被染黑了,所以最后染黑的点集必然是一棵子树. 可以得出的结论是,如果被染黑的节点在节点 \(a\) 的子树中,而 \(a\ ...

  3. [ POI 2017 ] Podzielno

    \(\\\) \(Description\) \(B\)进制数,每个数字\(i(i\in [0,B-1])\)有\(A_i\)个.用这些数字组成一个最大的\(B\)进制数\(X\)(不能有前导零,不需 ...

  4. QDUOJ ycb的ACM进阶之路 二进制多重背包

    ycb的ACM进阶之路 发布时间: 2017年5月22日 14:30   最后更新: 2017年5月22日 14:31   时间限制: 1000ms   内存限制: 128M 描述 ycb是个天资聪颖 ...

  5. 利用Crowbar抓取网页异步加载的内容 [Python俱乐部]

    利用Crowbar抓取网页异步加载的内容 [Python俱乐部] 利用Crowbar抓取网页异步加载的内容 在做 Web 信息提取.数据挖掘的过程中,一个关键步骤就是网页源代码的获取.但是出于各种原因 ...

  6. 设计模式总结(《Head First设计模式》学习总结)

    写在前面: 学习过程中不仅要熟练掌握技能,理论的消化吸收也必不可少.虽然个人更倾向于学习技术类的东西(短时间的精力投入很快就能看到成效...),但看了很多前辈的经验总结后才知道理论性的东西是绝对不能忽 ...

  7. 借助Python来实现的定量城市研究

    一.数据处理基础 (一)数据分析的概念 城市数据分析,可以从数据分析的广义和狭义两个角度来看: 狭义的数据分析是指根据分析目的,采用对比分析.分组分析.交叉分析和回归分析等分析方法,对相关城市数据(包 ...

  8. 基于bert_bilstm_crf的命名实体

    前言 本文将介绍基于pytorch的bert_bilstm_crf进行命名实体识别,涵盖多个数据集.命名实体识别指的是从文本中提取出想要的实体,本文使用的标注方式是BIOES,例如,对于文本虞兔良先生 ...

  9. 如何一秒钟从头构建一个 ASP.NET Core 中间件

    前言 其实地上本没有路,走的人多了,也便成了路. -- 鲁迅 就像上面鲁迅说的那样,其实在我们开发中间件的过程中,微软并没有制定一些策略或者文档来约束你如何编写一个中间件程序, 但是其中却存在者一些最 ...

随机推荐

  1. Appium+python的单元测试框架unittest(4)——断言(转)

    (原文:https://www.cnblogs.com/fancy0158/p/10051576.html) 在我们编写的测试用例中,测试步骤和预期结果是必不可少的.当我们运行测试用例时,得到一个运行 ...

  2. qs.js - 更好的处理url参数

    第一次接触 qs 这个库,是在使用axios时,用于给post方法编码,在使用过程中,接触到了一些不同的用法,写在这里分享一下. qs.parse qs.parse 方法可以把一段格式化的字符串转换为 ...

  3. TPO 02 - The Origins of Cetaceans

    TPO 02 - The Origins of Cetaceans It should be obvious that cetaceans[n. 鲸目动物]-whales, porpoises [n. ...

  4. 十几行代码带你用Python批量实现txt转xls,方便快捷

    前天看到后台有一兄弟发消息说目前自己有很多txt 文件,领导要转成xls文件,问用python怎么实现,我在后台简单回复了下,其实完成这个需求方法有很多,因为具体的txt格式不清楚,当然如果是有明确分 ...

  5. while read读取文本内容

    读取文件给 while 循环 方式一: exec <FILE while read line do cmd done 方式二: cat FILE_PATH |while read line do ...

  6. DOM---文档对象模型(Document Object Model)的基本使用

    一.DOM简介 文档对象模型(Document Object Model,简称DOM),是W3C组织推荐的处理可扩展置标语言的标准编程接口.它是一种与平台和语言无关的应用程序接口(API),它可以动态 ...

  7. curl常用用法

    -v显示请求详细信息 curl www.baidu.com -v -X 指定请求方式 GET请求 curl -X GET http://localhost:8080/search?data=123 # ...

  8. [shell] awk学习

    awk处理最后一行 awk '{if(NR>1)print a;a=$0}END{print a="b"}' file awk 'BEGIN{getline a}{print ...

  9. Oracle数据库拼音首字母模糊搜索

    1.建立函数 CREATE OR REPLACE FUNCTION F_PINYIN(P_NAME IN VARCHAR2) RETURN VARCHAR2 AS V_COMPARE ); V_RET ...

  10. 6. B树

    一.B 树是一种多叉平衡查找树 相较于二叉结构的红黑树,B 树是多叉结构,所以在元素数量非常多的情况下,B 树的高度不会像二叉树那么大,从而保证查询效率. 一棵含 n 个结点的 B 树的高度 h = ...