NOIP做题练习(day4)
A - 同花顺
题解
30分做法
爆搜即可。
60分做法
去重+贪心。
100分做法
去重+贪心后,我们要寻找一段符合条件的最长同花上升子序列 \(L\),\(n-L\) 即为所求的答案。
首先对于相同的花色,用一个队列去维护以每一张牌作结尾时能在序列中的所有牌(即维护首尾指针),然后统计出这些牌的数量,取较大值,答案就是牌的总数与这个值得差值。
枚举同花顺在已有的牌里面的最后一张牌,寻找可能的“第一张牌”,令 \(last\) 为当前牌的最后一张牌时,“可能的第一张牌”。
如果当前牌的数值是 \(a\),\(last\) 这张牌的数值是 \(b\),则显然要满足 \(a-b+1≤n\);
数值都是排好序的,随着“最后一张牌”的递增,“可能的第一张牌”显然是不降的,从前往后 \(O(N)\)进行扫一遍即可得到答案。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#define gI gi
#define itn int
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n, ans, sum, m, ton[100003];
bool vis[100003];
struct Node
{
int hs, sz;
bool operator < (const Node &x) const
{
return hs < x.hs || (hs == x.hs && sz < x.sz);
}
bool operator == (const Node &x) const
{
return (hs == x.hs && sz == x.sz);
}
} a[100003];
inline bool cmp(Node x, Node y)
{
if (x.hs == y.hs) return x.sz < y.sz;
return x.hs < y.hs;
}
inline bool pd()
{
for (int i = 1; i < n; i+=1) if (a[i].hs != a[i + 1].hs || (a[i].sz < a[i + 1].sz - 1)) return false;
return true;
}
int main()
{
File("card");
n = gi(); m = n;
bool fl = true;
int Max = 0;
for (int i = 1; i <= n; i+=1)
{
a[i].hs = gi(), a[i].sz = gi(); if (a[i].sz > n) fl = false; Max = max(Max, a[i].hs);
}
sort(a + 1, a + 1 + n);
if (pd()) {puts("0"); return 0;}
n = unique(a + 1, a + 1 + n) - (a + 1);
int head = 0, tail;
for (int i = 1; i <= n; i+=1)
{
if (i == 1 || a[i].hs != a[i - 1].hs) tail = i;
while (a[i].sz - a[tail].sz + 1 > m) ++tail;
head = max(head, i - tail + 1);
}
printf("%d\n", m - head);
return 0;
}
B - 做实验
题目描述
有一天,你实验室的老板给你布置的这样一个实验。
首先他拿出了两个长度为 \(n\) 的数列 \(a\) 和 \(b\),其中每个 \(a_i\) 以二进制表示一个集合。例如数字 \(5 = (101)_2\) 表示集合 {\(1; 3\)}。第 \(i\) 次实验会准备一个小盒子,里面装着集合 \(a_i\) 所有非空子集的纸条。老板要求你从中摸出一张纸条,如果满足你摸出的纸条是 \(a_i\) 的子集而不是 \(a_{i−b_i}\),\(a_{i−b_{i+1}}\),\(...\),\(a_{i}−1\) 任意一个的子集,那么你就要 \(***\);反之,你就逃过一劫。
令你和老板都没有想到的是,你竟然每次都逃过一劫。在庆幸之余,为了知道这件事发生的概率,你想要算出每次实验有多少纸条能使你 \(***\)
输入格式
第一行一个数字 \(n\)。
接下来 \(n\) 行,每行两个整数,分别表示 \(a_i\) 和 \(b_i\)。
输出格式
\(n\) 行,每行一个数字,表示第 \(i\) 次实验能使你 \(***\) 的纸条数。
样例输入 1
3
7 0
15 1
3 1
样例输出 1
7
8
0
数据范围
对于 \(30 \%\) 的数据,\(n, a_i, b_i ≤ 100\)
对于 \(70 \%\) 的数据,\(n, a_i, b_i ≤ 60000\)
对于 \(100 \%\) 的数据,\(n, a_i, b_i ≤ 10^5\)
保证所有的 \(a_i\) 不重复,\(b_i < i\)
题解
题目大意 :有一个长度为 \(n\) 的数列,其中数列的每项 \(a[i]\)是一个集合,给出 \(n\) 个询问,对于给定两个序列 \(a[i]\)和 \(b[i]\),问对于每个 \(a[i]\),它的子集里面有多少不是\(a[i-b[i]] a[i-b[i]+1]… a[i-1]\) 的子集
这个问题的关键在于两个问题,一是枚举 \(a[i]\)的子集,二是记录对于 \(a[i]\)的每一个子集的状态什么时候在数列上出现过?
即问题的关键:枚举子集、记录前一次出现的位置
枚举依据题意 \(S\) 的子集做法:for( int i=s ; i ; i=(i-1)&s )
- 设 \(f[s]\)为 \(s\) 的这个子集最后一次出现在哪一个 \(a[i]\) 当中
- 为什么是对应最后一次出现 \(s\) 状态的 \(a[ \ ]\)位置?对于序列从前往后处理 \(a[i]\),且询问子集满足不在 \(a[i-b[i]] a[i-b[i]+1]… a[i-1]\) 这些之中。
- 从 \(a[1]\)到 \(a[n]\)依次处理。对 \(a[i]\),枚举其所有的子集 \(s\),若 \(f[s] < i-b[i]\),则答案\(+1\)。同时更新 \(f[s]\)。
不难得出\(AC\)代码
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#define gI gi
#define itn int
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n, m, a, b, ans, sum, pos[100003], tem, tot, cnt;
int main()
{
File("test");
n = gi();
memset(pos, -1, sizeof(pos));
for (itn i = 1; i <= n; i+=1)
{
a = gi(), b = gi();
tem = a; ans = 0;
while (tem)
{
if (pos[tem] < i - b) ++ans;
pos[tem] = i;
tem = (tem - 1) & a;
}
printf("%d\n", ans);
}
return 0;
}
C - 拯救世界
题解
\(tarjan\)缩点后重新建图,然后跑一遍最长路,将起点\(s\)到所有酒吧的最长路取\(\max\)即可。
代码
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <cctype>
#include <queue>
#define gI gi
#define itn int
#define File(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout)
using namespace std;
inline int gi()
{
int f = 1, x = 0; char c = getchar();
while (c < '0' || c > '9') {if (c == '-') f = -1; c = getchar();}
while (c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();}
return f * x;
}
int n, m, U[500003], V[500003], head[500003], nxt[500003], ver[500003], edge[500003], tot, cnt, sum[500003], ans, W[500003], Top, dgs;
int s, p, q[500003], low[500003], dis[500003], dfn[500003], sy[500003], sta[500003], num, vis[500003];
inline void add(int u, int v)
{
ver[++tot] = v, nxt[tot] = head[u], head[u] = tot;
}
inline void add1(int u, int v, int w)
{
ver[++tot] = v, edge[tot] = w, nxt[tot] = head[u], head[u] = tot;
}
void Tarjan(int u)
{
dfn[u] = low[u] = ++num, vis[u] = 1, sta[++Top] = u;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i];
if (!dfn[v])
{
Tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (vis[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u])
{
++dgs;
do
{
int y = sta[Top];
sum[dgs] = sum[dgs] + W[y];
vis[y] = 0;
sy[y] = dgs;
} while (sta[Top--] != u);
}
}
inline void SPFA()
{
queue <int> q;
for (int i = 1; i <= dgs; i+=1) dis[i] = 0;
int pp = sy[s];
vis[pp] = 1, dis[pp] = sum[pp], q.push(pp);
while (!q.empty())
{
int u = q.front(); q.pop(); vis[u] = 0;
for (int i = head[u]; i; i = nxt[i])
{
int v = ver[i], w = edge[i];
if (dis[v] < dis[u] + w)
{
dis[v] = dis[u] + w;
if (!vis[v])
{
vis[v] = 1;
q.push(v);
}
}
}
}
}
int main()
{
File("save");
n = gi(), m = gi();
for (int i = 1; i <= m; i+=1)
{
U[i] = gi(), V[i] = gi();
add(U[i], V[i]);
}
for (int i = 1; i <= n; i+=1) W[i] = gi();
s = gi(), p = gi();
for (int i = 1; i <= p; i+=1) q[i] = gi();
for (int i = 1; i <= n; i+=1)
{
if (!dfn[i]) Tarjan(i);
}
memset(head, 0, sizeof(head));
memset(ver, 0, sizeof(ver));
memset(edge, 0, sizeof(edge));
memset(nxt, 0, sizeof(nxt));
tot = 0;
for (int i = 1; i <= m; i+=1)
{
if (sy[U[i]] != sy[V[i]]) add1(sy[U[i]], sy[V[i]], sum[sy[V[i]]]);
}
//memset(vis, 0, sizeof(vis));
SPFA();
ans = 0;
for (itn i = 1; i <= p; i+=1)
{
ans = max(ans, dis[sy[q[i]]]);
}
printf("%d\n", ans);
return 0;
}
总结
要善于拿部分分。
学会建模。
各种算法的模板要打熟练。
NOIP做题练习(day4)的更多相关文章
- noip做题记录+挑战一句话题解?
因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...
- NOIP做题练习(day2)
A - Reign 题面 题解 最大子段和+\(DP\). 预处理两个数组: \(p[i]\)表示 \(i\) 之前的最大子段和. \(l[i]\)表示 \(i\) 之后的最大子段和. 最后直接输出即 ...
- NOIP做题练习(day1)
A - Xenny and Alternating Tasks 题面 题解 枚举第一天是谁做,将两个答案取\(min\)即可. 代码 #include <iostream> #includ ...
- $NOIp$做题记录
虽然去年做了挺多了也写了篇一句话题解了但一年过去也忘得差不多了$kk$ 所以重新来整理下$kk$ $2018(4/6$ [X]积木大赛 大概讲下$O(n)$的数学方法. 我是从分治类比来的$QwQ$. ...
- NOIP做题练习(day5)
A - 中位数图 题面 题解 先找出题意中的\(b\)所在的位置. 再以这个位置为中心,向右\(for\)一遍有多少个大于/小于该数的数 大于就\(++cs\) 小于就\(--cs\). 因为这个数是 ...
- NOIP做题练习(day3)
A - 军队 问题描述 给定一个有 \(n\) 个队伍的人组成的序列,第 \(i\) 个队伍 \(i\) 有 \(s[i]\)个人组成,一个 \(l\) 到 \(r\)的子序列是合法的,当且仅当\(( ...
- NOIP初赛:完善程序做题技巧
最近写的文章好像还很多的.那么今天我们来讨论NOIP初赛的题型--完善程序.完善程序相对是比较难的题目了.全卷100分,完善程序占了大概26分,占比非常大.如果和英语考试试卷做比较,相当于首字母填空( ...
- [日记&做题记录]-Noip2016提高组复赛 倒数十天
写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...
- CodeM美团点评编程大赛复赛 做题感悟&题解
[T1] [简要题意] 长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...
随机推荐
- ASP.NET Identity系列教程-4【Identity高级技术】
https://www.cnblogs.com/r01cn/p/5194257.html 15 ASP.NET Identity高级技术 In this chapter, I finish my de ...
- stringstream使用小结
1.头文件:#include<sstream> 2.stringstream是C++提供的串流(stream)物件 3.clear()重置流的标志状态:str()清空流的内存缓冲,重复使用 ...
- STM32CubeMX自建MDK工程的基本步骤
根据需要调节各总线频率 最下方选项,√去掉,不用实时更新库,选择自己库所在路径就好. 点击左侧, 选择"Code Generator", 选择.c 和 .h文件不分开 最后,点击& ...
- PHP错误日志文件Warning:PHP Startup: Unable to load dynamic library...
由于我的环境是通过源码编译安装的,安装的时候配置信息和一些其他扩展没安装或设置好: php.err文件一直有这些提示,虽然不影响服务启动,但是看着心好累啊,决定要消灭他们. 问题描述: 出现原因: 上 ...
- 中文 json_encode之后字符长度问题
问题描述: 将某个字符串$str 进行json编码,即json_encode($str)后变成Unicode字符存入数据库,会发现中文的长度明明没有超过设置的字符长度最大值,但是却抛出字段长度过长错误 ...
- .NetCore学习笔记:三、基于AspectCore的AOP事务管理
AOP(面向切面编程),通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术.AOP是OOP的延续,是函数式编程的一种衍生范型.利用AOP可以对业务逻辑的各个部分进行隔离,从而使得业务逻辑 ...
- python数据分析学习(2)pandas二维工具DataFrame讲解
目录 二:pandas数据结构介绍 下面继续讲解pandas的第二个工具DataFrame. 二:pandas数据结构介绍 2.DataFarme DataFarme表示的是矩阵的数据表,包含 ...
- Vue中axios有关请求头的几点小结
在Vue前端中向后端发起http请求会有着两种写法:一种是在vue文件中直接导入axios模板,另外一种是使用Vue的属性$http. 1.在第一种方式中,在同一个工程中所添加的vue文件直接使用ax ...
- 《深入理解java虚拟机》读书笔记四——第五章
第五章 调优案例分析与实战
- 51Nod 1432 独木舟 (贪心)
n个人,已知每个人体重.独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? Input 第一行包含 ...