T1 [JZOJ1534] rank

题目描述

  小h和小R正在看之前的期末&三校联考成绩,小R看完成绩之后很伤心,共有n个学生,第i个学生有一个总成绩Xi,因为他的排名是倒数第k个,于是小R想知道那些成绩比他低(包括成绩和他一样)的同学的成绩,这样能让他没那么伤心。

数据范围

  $1 \leq N \leq 5 \times 10^6$,$0 \leq X \leq 10^5$

分析

  我以为我拿到了C组题,惊了

  数据量大数据值小,显然桶排序

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 5000005
#define M 100005 int n, k, x, mins = inf, maxs, s[M]; int main() {
scanf("%d%d", &n, &k);
for (int i = ; i <= n; i++) {
scanf("%d", &x); s[x]++;
mins = min(mins, x);
maxs = max(maxs, x);
}
int now = ;
for (int i = mins; i <= maxs; i++) {
while (s[i]--) {
if (++now > k) break;
printf("%d ", i);
}
if (now >= k) break;
} return ;
}

T2 [JZOJ1536] seek

题目描述

  俗话说“好命不如好名”,小h准备给他的宠物狗起个新的名字,于是他把一些英文的名字全抄下来了,写成一行长长的字符串,小h觉得一个名字如果是好名字,那么这个名字在这个串中既是前缀,又是后缀,即是这个名字从前面开始可以匹配,从后面开始也可以匹配,例如abc在abcddabc中既是前缀,也是后缀,而ab就不是,可是长长的字符让小h几乎昏过去了,为了给自己的小狗起个好名字,小h向你求救,并且他要求要将所有的好名字的长度都输出来。

数据范围

  $1 \leq \vert S \vert \leq 4 \times 10^5$

分析

  这题主要是考对 $KMP$ 算法的理解

  事实上这里只需要用到 $KMP$ 中的 $nxt$ 数组,即字符串每个前缀区间的前后缀最长匹配(不包含自身)

  首先原字符串肯定是符合题意的,而对于每个合法的区间,它的最长匹配前缀区间也是合法的

  所以只需要在求出 $nxt$ 数组后,依次输出所有合法区间就可以了

  当然这题用 $Hash$ 来做也是很简单的

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 400005 char s[N];
int nxt[N]; void find(int x) {
if (!x) return;
find(nxt[x]);
printf("%d ", x);
} int main() {
scanf("%s", s + );
int n = strlen(s + );
for (int i = , j = ; i <= n; i++) {
while (j && s[j + ] != s[i]) j = nxt[j];
if (s[j + ] == s[i]) j++;
nxt[i] = j;
}
find(n); return ;
}

T3 [JZOJ1537] pot

题目描述

  这个假期,小h在自家院子里种了许多花,它们围成了一个圈,从1..n编号,小h对每盆花都有一个喜好值xi,小h现在觉得这样一成不变很枯燥,于是他做了m个改动,每次把第ki盘花改成喜好值为di的花,然后小h要你告诉他,在这个花圈中,连续的最大喜好值是多少(不能整圈都选)。

数据范围

  $1 \leq N,M \leq 10^5$,$-10^3 \leq X \leq 10^3$

分析

  如果花盆是一条链的形状,那么这题就是一个很裸的线段树维护最大子区间和

  但是这是一个环,所以区间在左右端点处可能是连接着的

  我们发现穿过左右端点的最大子区间和,可以用区间和减去最小子区间来表示

  因此我们只需要再维护最小子区间和,最后在两者中取较大值

  还要注意不能整圈都取,即序列不含 $0$ 时最优解不能等于总区间和

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100005
#define lc (p << 1)
#define rc ((p << 1) | 1)
#define mid ((l + r) >> 1) int n, m, k, d, ans, zero; struct Tree {
int sum, la, ra, ma, li, ri, mi;
} t[N << ]; void pushup(int p) {
t[p].sum = t[lc].sum + t[rc].sum;
t[p].la = max(t[lc].la, t[lc].sum + t[rc].la);
t[p].ra = max(t[rc].ra, t[rc].sum + t[lc].ra);
t[p].ma = max(t[lc].ra + t[rc].la, max(t[lc].ma, t[rc].ma));
t[p].li = min(t[lc].li, t[lc].sum + t[rc].li);
t[p].ri = min(t[rc].ri, t[rc].sum + t[lc].ri);
t[p].mi = min(t[lc].ri + t[rc].li, min(t[lc].mi, t[rc].mi));
} void build(int p, int l, int r) {
if (l == r) {
scanf("%d", &t[p].sum);
t[p].la = t[p].ra = t[p].ma = t[p].sum;
t[p].li = t[p].ri = t[p].mi = t[p].sum;
if (!t[p].sum) zero++;
return;
}
build(lc, l, mid);
build(rc, mid + , r);
pushup(p);
} void update(int p, int l, int r, int x, int q) {
if (l > x || r < x) return;
if (l == r) {
if (!t[p].sum && q) zero--;
if (t[p].sum && !q) zero++;
t[p].sum = q;
t[p].la = t[p].ra = t[p].ma = t[p].sum;
t[p].li = t[p].ri = t[p].mi = t[p].sum;
return;
}
update(lc, l, mid, x, q);
update(rc, mid + , r, x, q);
pushup(p);
} int main() {
scanf("%d", &n);
build(, , n);
scanf("%d", &m);
for (int i = ; i <= m; i++) {
scanf("%d%d", &k, &d);
update(, , n, k, d);
if (t[].ma == t[].sum && !zero) ans = t[].sum - t[].mi;
else if (t[].mi == t[].sum && !zero) ans = t[].ma;
else ans = max(t[].ma, t[].sum - t[].mi);
printf("%d\n", ans);
} return ;
}

T4 [JZOJ3512] show

题目描述

  有三支队伍,分别是A,B,C。有n个游戏节目,玩第i个游戏,队伍A可以得到的分数是A[i],队伍B可以得到的分数是B[i],队伍C可以得到的分数是C[i]。由于时间有限,可能不是每个节目都能玩,于是节目主持人决定要从n个游戏节目里面挑选至少k个节目出来(被选中的节目不分次序),使得队伍A成为赢家。队伍A能成为赢家的条件是队伍A的总得分要比队伍B的总得分要高,同时也要比队伍C的总得分要高。节目主持人有多少种不同的选取方案?

数据范围

  对于 $40\%$ 的数据,$2 \leq N \leq 20$

  对于 $100\%$ 的数据,$2 \leq N \leq 34$,$1 \leq K \leq min(N,7)$,$1 \leq A,B,C \leq 10^9$

分析

  防AK题,当然是选择秒打暴力啊

  仔细观察,会发现这题的数据范围很诡异,状压显然是不行的,又好像没什么方法可以剪枝

  但是,题目中给了一个很小的 $k$,我们会想到用总合法方案数减去不满足 $k$ 限制的合法方案数得到答案

  在不满足 $k$ 的限制范围中,枚举的方案数量最多是 $\sum\limits_{i=0}^6 \binom{34}{i}$,即 $1676116$ 种,这是不会超时的

  然后在求总合法方案数时,直接搜索时肯定过不了的,我们可以把前一半节目和后一半节目分为两部分

  对于每个部分,枚举的方案数最多为 $2^{17}$,我们可以求出两个部分中每种方案得到的一对值 $(ab_1,ac_1)$,$(ab_2,ac_2)$,其中 $ab$ 为 $A$ 组总得分减去 $B$ 组总得分,$ac$ 为 $A$ 组总得分减去 $C$ 组总得分

  显然,一种完整方案要成立,必须同时满足 $ab_1+ab_2>0$ 和 $ac_1+ac_2>0$

  所以我们可以枚举第一部分中的所有方案,在第二部分中找出与之匹配能够成立的方案

  当然这样就需要用树状数组/线段树之类的数据结构来保存第二部分中的所有方案,同时还需要离散化/动态开点

  时间复杂度为 $O(2^{17} \, log \; 2^{17}+1676116) \doteq O(1807193)$

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 40
#define M (1 << 17) + 5 int n, k, t1, t2, t, tr[M << ];
ll ansk, ans, a[N], b[N], c[N]; struct Data {ll ab, ac;} d1[M], d2[M];
struct Node {ll x, y; int mark;} d[M << ]; bool cmp1(Data x, Data y) {return x.ac < y.ac;}
bool cmp2(Data x, Data y) {return x.ac > y.ac;}
bool cmp(Node x, Node y) {return x.x < y.x;}; void dfsk(int x, int sum, ll sa, ll sb, ll sc) {
if (sum == k) return;
if (sa > sb && sa > sc) ansk++;
for (int i = x + ; i <= n; i++)
dfsk(i, sum + , sa + a[i], sb + b[i], sc + c[i]);
} void dfs1(int x, ll sa, ll sb, ll sc) {
d1[++t1].ab = sa - sb, d1[t1].ac = sa - sc;
for (int i = x + ; i <= (n >> ); i++)
dfs1(i, sa + a[i], sb + b[i], sc + c[i]);
} void dfs2(int x, ll sa, ll sb, ll sc) {
d2[++t2].ab = sa - sb, d2[t2].ac = sa - sc;
for (int i = x + ; i <= n; i++)
dfs2(i, sa + a[i], sb + b[i], sc + c[i]);
} int lowbit(int x) {return x & -x;} void update(int x) {
while (x <= t) tr[x]++, x += lowbit(x);
} int query(int x) {
int sum = ;
while (x) sum += tr[x], x -= lowbit(x);
return sum;
} int main() {
scanf("%d%d", &n, &k);
for (int i = ; i <= n; i++) scanf("%lld", a + i);
for (int i = ; i <= n; i++) scanf("%lld", b + i);
for (int i = ; i <= n; i++) scanf("%lld", c + i);
dfsk(, , , , ); dfs1(, , , ); dfs2(n >> , , , );
for (int i = ; i <= t1; i++)
d[i].x = d1[i].ab, d[i].y = i, d[i].mark = ;
for (int i = ; i <= t2; i++)
d[t1 + i].x = -d2[i].ab, d[t1 + i].y = i, d[t1 + i].mark = ;
sort(d + , d + t1 + t2 + , cmp);
d[].x = -;
for (int i = ; i <= t1 + t2; i++) {
if (d[i].x != d[i - ].x) t++;
if (!d[i].mark) d1[d[i].y].ab = t;
else d2[d[i].y].ab = t;
}
sort(d1 + , d1 + t1 + , cmp1);
sort(d2 + , d2 + t2 + , cmp2);
for (int i = , j = ; i <= t1; i++) {
while (j <= t2 && d1[i].ac + d2[j].ac > )
update(d2[j].ab), j++;
ans += query(d1[i].ab - );
}
printf("%lld\n", ans - ansk); return ;
}

2019-08-13 纪中NOIP模拟B组的更多相关文章

  1. 2019-08-21 纪中NOIP模拟A组

    T1 [JZOJ6315] 数字 题目描述

  2. 2019-08-20 纪中NOIP模拟A组

    T1 [JZOJ6310] Global warming 题目描述 给定整数 n 和 x,以及一个大小为 n 的序列 a. 你可以选择一个区间 [l,r],然后令 a[i]+=d(l<=i< ...

  3. 2019-08-18 纪中NOIP模拟A组

    T1 [JZOJ6309] 完全背包 题目描述

  4. 2019-08-15 纪中NOIP模拟B组

    T1 [JZOJ3455] 库特的向量 题目描述 从前在一个美好的校园里,有一只(棵)可爱的弯枝理树.她内敛而羞涩,一副弱气的样子让人一看就想好好疼爱她.仅仅在她身边,就有许多女孩子想和她BH,比如铃 ...

  5. 2019-08-01 纪中NOIP模拟B组

    T1 [JZOJ2642] 游戏 题目描述 Alice和Bob在玩一个游戏,游戏是在一个N*N的矩阵上进行的,每个格子上都有一个正整数.当轮到Alice/Bob时,他/她可以选择最后一列或最后一行,并 ...

  6. 2019-08-25 纪中NOIP模拟A组

    T1 [JZOJ6314] Balancing Inversions 题目描述 Bessie 和 Elsie 在一个长为 2N 的布尔数组 A 上玩游戏. Bessie 的分数为 A 的前一半的逆序对 ...

  7. 2019-08-23 纪中NOIP模拟A组

    T1 [JZOJ2908] 矩阵乘法 题目描述 给你一个 N*N 的矩阵,不用算矩阵乘法,但是每次询问一个子矩形的第 K 小数. 数据范围 对于 $20\%$ 的数据,$N \leq 100$,$Q ...

  8. 2019-08-20 纪中NOIP模拟B组

    T1 [JZOJ3490] 旅游(travel) 题目描述 ztxz16如愿成为码农之后,整天的生活除了写程序还是写程序,十分苦逼.终于有一天,他意识到自己的生活太过平淡,于是决定外出旅游丰富阅历. ...

  9. 2019-08-09 纪中NOIP模拟B组

    T1 [JZOJ1035] 粉刷匠 题目描述 windy有N条木板需要被粉刷. 每条木板被分为M个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上一段连续的格子,然后涂上一 ...

  10. 2019-08-17 纪中NOIP模拟B组

    T1 [JZOJ3503] 粉刷 题目描述 鸡腿想到了一个很高(sha)明(bi)的问题,墙可以看作一个N*M的矩阵,有一些格子是有污点的.现在鸡腿可以竖着刷一次,覆盖连续的最多C列,或者横着刷一次, ...

随机推荐

  1. w13scan扫描器的使用

    0x01 w13scan第三方包下载 环境:python3以上 下载:pip install w13scan 0x02 利用w13scan API接口编写w13scan.py from W13SCAN ...

  2. C语言 运算符

    C语言 运算符 运算符优先级别 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成员 ...

  3. python类详细说明、常用内置方法和self的作用

    一.类的定义 在Python中,一切皆对象,即便是类本身,也是一种type类型的特殊对象. class Person: def __init__(self, name, age): self.name ...

  4. 数据结构(集合)学习之Map(一)

    集合 框架关系图: 补充:HashTable父类是Dictionary,不是AbstractMap. Map: Map(接口)和Collection都属于集合,但是Map不是Collection的子类 ...

  5. 转载 selenium_对浏览器操作、鼠标操作等总结

    https://www.jianshu.com/p/7a4414082ce2 查看环境conda info --env 激活环境conda activate machine 路径改成H:cd H:\p ...

  6. sql 根据查询的记录生成序号的几种方式

    row_number()  order() 函数会为查询出来的每一行记录生成一个序号,依次排序且不会重复,注意使用row_number函数时必须要用over子句选择对某一列进行排序才能生成序号. ra ...

  7. 【转】Servlet 九大对象和四个作用域

    隐式对象 说明 request 转译后对应HttpServletRequest/ServletRequest对象 response 转译后对应HttpServletRespons/ServletRes ...

  8. LINUX 概述

    初识linux Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程和多CPU的操作系统.它能运行主要的UNIX工具软件.应用程序和网络协 ...

  9. P1282 多米诺骨牌【dp】

    P1282 多米诺骨牌 提交 20.02k 通过 6.30k 时间限制 1.00s 内存限制 125.00MB 题目提供者洛谷 难度提高+/省选- 历史分数100 提交记录 查看题解 标签   查看算 ...

  10. PAT (Advanced Level) Practice 1035 Password (20 分)

    To prepare for PAT, the judge sometimes has to generate random passwords for the users. The problem ...