Day1

T1 转圈游戏

Link

一句话题意:

让你求 \({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 火柴排队

Link

先简化问题。给定我们两个序列,我们可以任意交换这两个序列中相邻的两个数。

让你最小化 \(\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 货车运输

Link

好像不用简化问题(大雾)。

这种图论模型,我们不是很好做,所以我们考虑把它转化为我们熟悉的问题(比如

树上问题)。

实际上,当两个点有重边的时候,我们会尽量选边权比较大的边走(很显然吧)。

所以,我们考虑对整个图求一遍最大生成树。这就转化为我们熟悉的树上问题。

求树上路径边权的最小值,直接上树剖套线段树来维护。

如果你这个题不确定这么写是对的,对拍会证明一切

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 积木大赛

Link

好像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 花匠

Link

一句话题意:给定一个序列,让你求把这个序列变成中间这个数比旁边两个数低或高的最小操作次数,

也就是波浪形的(可这样真的好看吗)

我们设 \(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 真题练习的更多相关文章

  1. [NOIP 2014复习]第三章:动态规划——NOIP历届真题回想

    背包型动态规划 1.Wikioi 1047 邮票面值设计 题目描写叙述 Description 给定一个信封,最多仅仅同意粘贴N张邮票,计算在给定K(N+K≤40)种邮票的情况下(假定全部的邮票数量都 ...

  2. NOIp 2015真题模拟赛 By cellur925

    果然我还是最菜的==不接受反驳== Day1 T1:神奇的幻方 思路:直接模拟即可,由于当前放法只与上一放法有关系,用两个变量记录一下即可.10分钟内切掉== 预计得分:100分 实际得分:100分 ...

  3. NOIP提高真题整理(2011-2018)-标签

    加粗的后面应该会有相应的简单解析(如果没咕的话:)). 2011 day1 T1:铺地毯:逆着铺 T2:选择客栈:按颜色分类枚举+二分答案 T3:Mayan游戏:大模拟dfs+剪枝 day2 T1:计 ...

  4. 历年NOIP真题总结

    前言:最近把历年的NOIP真题肝了一遍(还有3个紫题先咕掉了),主要是到1998年的提高组的题.把题目的做题简要思路搁在这儿,一个是为了考前翻一翻,想想自己的哪些思路要梳理的什么什么的,反正怎么说呢, ...

  5. NOIP真题汇总

    想想在NOIP前总得做做真题吧,于是长达一个月的刷题开始了 涉及2008-2016年大部分题目 NOIP [2008] 4/4 1.传纸条:清真的三维DP 2.笨小猴:字符串模拟 3.火柴棒等式:打表 ...

  6. Noip前的大抱佛脚----Noip真题复习

    Noip前的大抱佛脚----Noip真题复习 Tags: Noip前的大抱佛脚 Noip2010 题目不难,但是三个半小时的话要写四道题还是需要码力,不过按照现在的实力应该不出意外可以AK的. 机器翻 ...

  7. NOIP真题索引

    NOIP真题索引 NOIP2019 Day 1 格雷码 括号树 树上的数 Day 2 Emiya 家今天的饭 划分 树的重心 NOIP2018 Day 1 铺设道路 货币系统 赛道修建 Day 2 旅 ...

  8. 历年真题 未完成(Noip 2008 - Noip 2017)

    Noip 2008 :全部 Noip 2009 :全部 Noip 2010 :AK Noip 2011 :AK Noip 2012 : Vigenère 密码,国王游戏,开车旅行 Noip 2013 ...

  9. 蓝桥杯Java真题解析

    上个月参加蓝桥杯省赛拿了个省一,自从比赛完之后就一直没怎么写代码了,还有一个多月就要国赛了,从现在开始准备下国赛,但是我也不想学什么算法,而且我还在准备考研,所以就打算只做下历年的真题,争取国赛拿个国 ...

随机推荐

  1. 【Android】SlidingTabLayout实现标题栏,教你制作title标题 简单易学。

    SlidingTabLayout 作者:程序员小冰,CSDN博客:http://blog.csdn.net/qq_21376985, QQ986945193 微博:http://weibo.com/m ...

  2. openresty(nginx+lua)初识

    1.新增项目配置文件: vim /usr/example/example1.conf --将以下内容加入example1.conf server { listen 80; server_name _; ...

  3. Jmeter逻辑控制器,简单操作

    1. 2. 循环控制器可以设置请求的循环次数或永久循环, .  作用:改控制器下的取样器请求可以循环运行. 3. 请求需要拖拽到循环控制器里, 4.循环次数乘以线程数 得到如下图: 成功了 二. 事务 ...

  4. Ajax请求携带Cookie

    目录 xhr ajax cookie跨域处理 客户端 服务端 服务端设置跨域的几种方式 方式一 重写addCorsMappings方法 方式二 对单个接口处理 方式三 @CrossOrigin注解 方 ...

  5. 启动Tomcat服务器端口被占用解决方法

    Caused by: java.net.BindException: Address already in use: bind 1.输入 netstat -ano|findstr 8080,回车,显示 ...

  6. ZT:通过Find命令找到你要找的东西

    https://os.51cto.com/art/202003/612049.htm find 命令有巨多的选项可以帮助你准确定位你在 Linux 系统上需要寻找的文件.这篇文章讨论了一系列非常有用的 ...

  7. jenkins打包前端项目报 error: index-pack died of signal 15 问题解决

    jenkins打包前端项目报 error: index-pack died of signal 15 问题解决 前几天用jenkins打包一个前端项目的时候出现了 error: index-pack ...

  8. WIN10自动修复失败无限循环

    网上解决方案大部分都是要重置电脑或者进pe修复系统,手头没有启动盘又不想重置电脑的可以照下边的操作试一试 1.先暂时禁用自动修复功能cmd管理员(winre可以进cmd)执行bcdedit bcded ...

  9. awk使用说明(复制别人的)

    来源:http://www.cnblogs.com/ggjucheng/archive/2013/01/13/2858470.html 简介 awk是一个强大的文本分析工具,相对于grep的查找,se ...

  10. [LeetCode]33. 搜索旋转排序数组(二分)

    题目 假设按照升序排序的数组在预先未知的某个点上进行了旋转. ( 例如,数组 [0,1,2,4,5,6,7] 可能变为 [4,5,6,7,0,1,2] ). 搜索一个给定的目标值,如果数组中存在这个目 ...