Noip 2013 真题练习
Day1
T1 转圈游戏
一句话题意:
让你求 \({x + m \times 10^k} \bmod n\) 的结果。
直接套上快速幂的板子。
code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define LL long long
LL n,m,k,x;
LL ksm(LL a,LL b)
{
LL res = 1;
for(; b; b >>= 1)
{
if(b & 1) res = res * a % n;
a = a * a % n;
}
return res;
}
int main()
{
scanf("%lld%lld%lld%lld",&n,&m,&k,&x);
int tmp = ksm(10,k) * m % n;
printf("%lld\n",(x+tmp)%n);
return 0;
}
T2 火柴排队
先简化问题。给定我们两个序列,我们可以任意交换这两个序列中相邻的两个数。
让你最小化 \(\displaystyle \sum (a[i]-b[i])^2\),的最小交换次数。
首先,一个结论就是 \(A\) 序列中第 \(k\) 大的一定要和 \(B\) 序列中 第 \(k\) 大的数相对应。
这样得到的序列肯定是最小的。
然后,我们就要求这两个序列变化成一一对应的(即上面那种情况)的最小交换次数。
我们可以先求出 \(A\) 序列中的每个数在 \(B\) 序列中对应的数出现的位置,这就可以得到另一个序列 \(C\)。
交换次数就是 \(C\) 的逆序对数(有点绕)。因为你最后肯定是让 \(C\) 序列升序排列。
你也可以把\(C\) 数组理解为要把 \(A\) 中的数变到第几位。
最后,不要忘记离散化一下。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int p = 1e8-3;
int n,ans,tr[100010],q[100010];
struct node
{
int x,id;
}a[100010],b[100010];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10+ch -'0'; ch = getchar();}
return s * w;
}
bool comp(node a,node b)
{
if(a.x == b.x) return a.id < b.id;
return a.x < b.x;
}
int lowbit(int x){return x & (-x);}
void chenge(int x,int val)
{
for(; x <= n; x += lowbit(x)) tr[x] += val;
}
int ask(int x)
{
int res = 0;
for(; x; x -= lowbit(x))
{
res = (res + tr[x]) % p;
}
return res % p;
}
int main()
{
n = read();
for(int i = 1; i <= n; i++)//离散化
{
a[i].x = read();
a[i].id = i;
}
for(int i = 1; i <= n; i++)
{
b[i].x = read();
b[i].id = i;
}
sort(a+1,a+n+1,comp); sort(b+1,b+n+1,comp);
for(int i = 1; i <= n; i++)
{
q[b[i].id] = a[i].id;//第i个大的数所对应的编号
}
for(int i = 1; i <= n; i++)
{
chenge(q[i],1);
int tmp = i - ask(q[i]);
ans = (ans + tmp) % p;
}
printf("%d\n",ans);
return 0;
}
T3 货车运输
好像不用简化问题(大雾)。
这种图论模型,我们不是很好做,所以我们考虑把它转化为我们熟悉的问题(比如
树上问题)。
实际上,当两个点有重边的时候,我们会尽量选边权比较大的边走(很显然吧)。
所以,我们考虑对整个图求一遍最大生成树。这就转化为我们熟悉的树上问题。
求树上路径边权的最小值,直接上树剖套线段树来维护。
如果你这个题不确定这么写是对的,对拍会证明一切
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N = 1e5+10;
int n,m,tot,q,u,v,num;
int head[N],dfn[N],siz[N],top[N],fa[N],f[N],son[N],w[N],dep[N],a[N];
struct node
{
int to,net,w;
}e[N<<1];
struct bian
{
int u,v,w;
}e2[N<<1];
#define l(o) tr[o].lc
#define r(o) tr[o].rc
#define sum(o) tr[o].sum
struct tree
{
int lc,rc,sum;
}tr[N<<2];
void add(int x,int y,int w)
{
e[++tot].w = w;
e[tot].to = y;
e[tot].net = head[x];
head[x] = tot;
}
int find(int x)
{
if(f[x] == x) return x;
else return f[x] = find(f[x]);
}
bool comp(bian a,bian b)
{
return a.w > b.w;
}
------------->//一下是线段树
void up(int o)
{
sum(o) = min(sum(o<<1),sum(o<<1|1));
}
void build(int o,int L,int R)
{
l(o) = L, r(o) = R;
if(L == R)
{
sum(o) = w[L];
return;
}
int mid = (L + R)>>1;
build(o<<1,L,mid);
build(o<<1|1,mid+1,R);
up(o);
}
int ask(int o,int L,int R)
{
int res = 2147483647;
if(L <= l(o) && R >= r(o)) return sum(o);
int mid = (l(o) + r(o))>>1;
if(L <= mid) res = min(res,ask(o<<1,L,R));
if(R > mid) res = min(res,ask(o<<1|1,L,R));
return res;
}
------------>// 以上是线段树
void max_tree(int m)//最大生成树
{
sort(e2+1,e2+m+1,comp);
for(int i = 1; i <= m; i++)
{
int x = e2[i].u, y = e2[i].v, w = e2[i].w;
int fx = find(x);
int fy = find(y);
if(fx == fy) continue;
f[fx] = fy;
add(x,y,w); add(y,x,w);
}
}
void get_tree(int x)
{
dep[x] = dep[fa[x]] + 1; siz[x] = 1;
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(to == fa[x] || dep[to]) continue;
fa[to] = x; a[to] = e[i].w;
get_tree(to);
siz[x] += siz[to];
if(siz[to] > siz[son[x]]) son[x] = to;
}
}
-------->// 树剖
void dfs(int x,int topp)
{
top[x] = topp; dfn[x] = ++num; w[dfn[x]] = a[x];
if(son[x]) dfs(son[x],topp);
for(int i = head[x]; i; i = e[i].net)
{
int to = e[i].to;
if(dfn[to]) continue;
dfs(to,to);
}
}
int query(int x,int y)
{
int ans = 2147483647;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]]) swap(x,y);
ans = min(ans,ask(1,dfn[top[x]],dfn[x]));
x = fa[top[x]];
}
if(dep[x] > dep[y]) swap(x,y);
ans = min(ans,ask(1,dfn[x]+1,dfn[y]));
return ans;
}
---------->//
int main()
{
scanf("%d%d",&n,&m);
for(int i = 1; i <= n; i++) f[i] = i;
for(int i = 1; i <= m; i++)
{
scanf("%d%d%d",&e2[i].u,&e2[i].v,&e2[i].w);
}
max_tree(m); get_tree(1);//预处理
dfs(1,1); build(1,1,n);
scanf("%d",&q);
for(int i = 1; i <= q; i++)
{
scanf("%d%d",&u,&v);
if(find(u) != find(v)) printf("%d\n",-1);//两个点之间不连通,就是无解情况
else printf("%d\n",query(u,v));
}
return 0;
}
Day2
T1 积木大赛
好像18年又出了和这个一模一样的原题。双倍经验
我们考虑当这个序列单调上升的时候,从 \(i\) 到 \(i+1\),我们只需要操作 \(a_{i+1} - a_i\) 次,因为你前面可以连带着
把这个也铺了。因此我们每个点对答案的贡献就是 \(a[i] - max(a[i],a[i-1])\) .
这个可以怎么理解呢?如果这个比前面的高度要小,我们可以在铺前面的时候把他也给铺了,比前面高度大的时候,
我们只需要在往上填几次就够了。
Code
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,a[100010],ans,maxn;
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&a[i]);
for(int i = 1; i <= n; i++)
{
if(a[i] > maxn)
{
ans += a[i] - maxn;
maxn = a[i];
}
else maxn = a[i];
}
printf("%d\n",ans);
return 0;
}
T2 花匠
一句话题意:给定一个序列,让你求把这个序列变成中间这个数比旁边两个数低或高的最小操作次数,
也就是波浪形的(可这样真的好看吗)
我们设 \(f[i][0]\) 表示到 \(i\) 时该下降时能选的最大的花的数量,\(f[i][1]\) 则表示 到\(i\) 时该上升时,能选的花的最大数量。
我们很容易能想出 O(\(n^2\)) 的dp
\(f[i][0] = max(f[i][0],f[j][1] + 1)\) ,\(f[i][1] = max(f[i][1],f[j][0]+1)\)
然后随便搞一下线段树优化 \(dp\) 就可以搞成 O(\(nlogn\)) 的啦。
可这样写代码比较长,并且比较难调。
我们考虑一下\(O(n)\) 的\(dp\)
- \(h[i] > h[i-1]\) 则 \(f[i][0] = f[i-1][1] + 1\) , 表示我们可以选这盆花。
- 则 \(f[i][1] = f[i-1][1]\) 表示我们可以让它成为新的波峰,来承接更多的花。
- \(h[i] < h[i-1]\) ,则 \(f[i][1] = f[i-1][0] + 1\) , 同理表示我们选这盆花
- 那么 \(f[i][0] = f[i-1][0]\) 即我们让他成为新的波谷,来承接更多的花。
Code:
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
int n,ans,h[2000010],f[200001][2];
int main()
{
scanf("%d",&n);
for(int i = 1; i <= n; i++) scanf("%d",&h[i]);
f[1][0] = f[1][1] = 1;
for(int i = 2; i <= n; i++)
{
if(h[i] > h[i-1])
{
f[i][0] = f[i-1][1] + 1;
}
else f[i][0] = f[i-1][0];//成为新的波谷
if(h[i] < h[i-1])
{
f[i][1] = f[i-1][0] + 1;//可以选上这盆花
}
else f[i][1] = f[i-1][1];//成为新的波峰
}
printf("%d\n",max(f[n][0],f[n][1]));
}
T3 华容道
太毒瘤了,不想写,先咕着吧。
Noip 2013 真题练习的更多相关文章
- [NOIP 2014复习]第三章:动态规划——NOIP历届真题回想
背包型动态规划 1.Wikioi 1047 邮票面值设计 题目描写叙述 Description 给定一个信封,最多仅仅同意粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定全部的邮票数量都 ...
- NOIp 2015真题模拟赛 By cellur925
果然我还是最菜的==不接受反驳== Day1 T1:神奇的幻方 思路:直接模拟即可,由于当前放法只与上一放法有关系,用两个变量记录一下即可.10分钟内切掉== 预计得分:100分 实际得分:100分 ...
- NOIP提高真题整理(2011-2018)-标签
加粗的后面应该会有相应的简单解析(如果没咕的话:)). 2011 day1 T1:铺地毯:逆着铺 T2:选择客栈:按颜色分类枚举+二分答案 T3:Mayan游戏:大模拟dfs+剪枝 day2 T1:计 ...
- 历年NOIP真题总结
前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...
- NOIP真题汇总
想想在NOIP前总得做做真题吧,于是长达一个月的刷题开始了 涉及2008-2016年大部分题目 NOIP [2008] 4/4 1.传纸条:清真的三维DP 2.笨小猴:字符串模拟 3.火柴棒等式:打表 ...
- Noip前的大抱佛脚----Noip真题复习
Noip前的大抱佛脚----Noip真题复习 Tags: Noip前的大抱佛脚 Noip2010 题目不难,但是三个半小时的话要写四道题还是需要码力,不过按照现在的实力应该不出意外可以AK的. 机器翻 ...
- NOIP真题索引
NOIP真题索引 NOIP2019 Day 1 格雷码 括号树 树上的数 Day 2 Emiya 家今天的饭 划分 树的重心 NOIP2018 Day 1 铺设道路 货币系统 赛道修建 Day 2 旅 ...
- 历年真题 未完成(Noip 2008 - Noip 2017)
Noip 2008 :全部 Noip 2009 :全部 Noip 2010 :AK Noip 2011 :AK Noip 2012 : Vigenère 密码,国王游戏,开车旅行 Noip 2013 ...
- 蓝桥杯Java真题解析
上个月参加蓝桥杯省赛拿了个省一,自从比赛完之后就一直没怎么写代码了,还有一个多月就要国赛了,从现在开始准备下国赛,但是我也不想学什么算法,而且我还在准备考研,所以就打算只做下历年的真题,争取国赛拿个国 ...
随机推荐
- element.ui 自定义样式问题
方法有很多种 自定义类名 <el-button class="search_button" @click="search">查询</el-bu ...
- 如何让SpringBoot工程在log/控制台中实时打印MyBatis执行的SQL语句
工程下载:https://files.cnblogs.com/files/xiandedanteng/gatling20200429-4.zip 其实就是一句话设置的事情,实现步骤: 在applica ...
- 20190919-02安装Xshell和CRT远程工具 000 008
Linux远程登录及相关工具介绍 Linux一般作为服务器使用,而服务器一般放在机房,你不可能在机房操作你的Linux服务器.这时我们就需要远程登录到Linux服务器来管理维护系统. Linux系统中 ...
- composer 国内镜像
本文列举一些最常用的国内镜像,配置国内镜像后可以提高composer包的下载速度.使用阿里云镜像的开发者较多,我也一直在使用这个镜像. 1. composer 中文网提供的中国全量镜像 https:/ ...
- 深入理解 vue 中 scoped 样式作用域的规则
哈喽!大家好!我是木瓜太香,今天我们来聊一个 vue 的样式作用域的问题,通常我们开发项目的时候是要在 style 上加上 scoped 来起到规定组件作用域的效果的,所以了解他们的规则也是很有必要的 ...
- springBoot 使用webSocket
本文(2019年6月18日 飞快的蜗牛博客) 有许多人走着走着,就迷失了自己,所以不论发生了什么,有时候抱着自己去静下来想想,要好好的对待自己:"钱塘江上潮信来,今日方知我是我", ...
- Solr专题(二)详解Solr查询参数
一.前言 上节我们讲到了怎样去搭建solr服务,作为全文检索引擎,怎样去使用也是比较关键的.Solr有一套自己的查询方式,所以我们需要另外花时间去学习它的这套模式. 启动solr solr start ...
- Java 合并、拆分PPT幻灯片
序 在日常使用PPT时,为了便于操作和管理文档,时常会遇到需要将PPT幻灯片进行合并或拆分的情况.本文将通过Java程序来演示如何进行上述操作. 示例要点: 1. 合并PPT幻灯片 1.1 将第一个P ...
- SpringCloud实战 | 第三篇:SpringCloud整合Nacos实现配置中心
前言 随着eureka的停止更新,如果同时实现注册中心和配置中心需要SpringCloud Eureka和SpringCloud Config两个组件;配置修改刷新时需要SpringCloud Bus ...
- 编译 lua cjson模块
使用文档:http://www.kyne.com.au/~mark/software/lua-cjson-manual.html下载地址:http://www.kyne.com.au/%7Emark/ ...