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)的更多相关文章

  1. noip做题记录+挑战一句话题解?

    因为灵巧实在太弱辽不得不做点noip续下命QQAQQQ 2018 积木大赛/铺设道路 傻逼原题? 然后傻逼的我居然检查了半天是不是有陷阱最后花了差不多一个小时才做掉我做过的原题...真的傻逼了我:( ...

  2. NOIP做题练习(day2)

    A - Reign 题面 题解 最大子段和+\(DP\). 预处理两个数组: \(p[i]\)表示 \(i\) 之前的最大子段和. \(l[i]\)表示 \(i\) 之后的最大子段和. 最后直接输出即 ...

  3. NOIP做题练习(day1)

    A - Xenny and Alternating Tasks 题面 题解 枚举第一天是谁做,将两个答案取\(min\)即可. 代码 #include <iostream> #includ ...

  4. $NOIp$做题记录

    虽然去年做了挺多了也写了篇一句话题解了但一年过去也忘得差不多了$kk$ 所以重新来整理下$kk$ $2018(4/6$ [X]积木大赛 大概讲下$O(n)$的数学方法. 我是从分治类比来的$QwQ$. ...

  5. NOIP做题练习(day5)

    A - 中位数图 题面 题解 先找出题意中的\(b\)所在的位置. 再以这个位置为中心,向右\(for\)一遍有多少个大于/小于该数的数 大于就\(++cs\) 小于就\(--cs\). 因为这个数是 ...

  6. NOIP做题练习(day3)

    A - 军队 问题描述 给定一个有 \(n\) 个队伍的人组成的序列,第 \(i\) 个队伍 \(i\) 有 \(s[i]\)个人组成,一个 \(l\) 到 \(r\)的子序列是合法的,当且仅当\(( ...

  7. NOIP初赛:完善程序做题技巧

    最近写的文章好像还很多的.那么今天我们来讨论NOIP初赛的题型--完善程序.完善程序相对是比较难的题目了.全卷100分,完善程序占了大概26分,占比非常大.如果和英语考试试卷做比较,相当于首字母填空( ...

  8. [日记&做题记录]-Noip2016提高组复赛 倒数十天

    写这篇博客的时候有点激动 为了让自己不颓 还是写写日记 存存模板 Nov.8 2016 今天早上买了两个蛋挞 吃了一个 然后就做数论(前天晚上还是想放弃数论 但是昨天被数论虐了 woc noip模拟赛 ...

  9. CodeM美团点评编程大赛复赛 做题感悟&题解

    [T1] [简要题意]   长度为N的括号序列,随机确定括号的方向:对于一个已确定的序列,每次消除相邻的左右括号(右左不行),消除后可以进一步合并和消除直到不能消为止.求剩下的括号的期望.\(N \l ...

随机推荐

  1. PAT (Basic Level) Practice (中文)1033 旧键盘打字 (20 分)

    旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及坏掉的那些键,打出的结果文字会是怎样? 输入格式: 输入在 2 行中分别给出坏掉的那些键.以及应该输入 ...

  2. Give me five !

    @media only screen and (max-width: 360px) { #friedsGroup { grid-template-columns:1fr!important; } } ...

  3. 一个扩展搜索API的优化过程

    概述 API 是一个服务的门面,就像衣装是人的形象一样. 优雅的 API 设计,能让业务方使用起来倍儿爽,提升开发效率,降低维护成本:糟糕的 API 设计,则让业务方遭心,陷入混沌. 本文将展示一个扩 ...

  4. jQuery 判断页面上下滚动

    var t = 0, b = 0; $(window).scroll(function(){ t = $(this).scrollTop(); if(b < t){ console.log('向 ...

  5. Winform递归绑定树节点

    /// <summary> /// 绑定树节点 /// </summary> /// <param name="pid"></param& ...

  6. jQuery---手风琴案例+stop的使用(解决动画队列的问题)

    手风琴案例+stop的使用(解决动画队列的问题) stop();// 停止当前正在执行的动画 <!DOCTYPE html> <html lang="en"> ...

  7. Qt Installer Framework翻译(7-7)

    脚本API 下表总结了可以在控制器和组件脚本中使用的全局JavaScript对象. QMessageBox 提供一个模式对话框,通知用户或询问用户问题并接收答案 buttons 提供可在安装程序页面上 ...

  8. 类的成员和属性_python

    一.字段和方法分类 方法分类: 二.属性(将方法伪装成字段) 三种伪装方式:@property  @perr.setter @perr.deleter 属性使用的场景:分页 三.公有成员和私有成员 私 ...

  9. Wannafly Camp 2020 Day 2E 阔力梯的树 - set,启发式合并

    搞一波启发式合并即可 #include <bits/stdc++.h> using namespace std; #define int long long #define iter se ...

  10. loj6277 数列分块入门题1

    裸题分块. #include <bits/stdc++.h> using namespace std; ],b[],n,m,t1,t2,t3,t4,sq; int main(){ ios: ...