「NOIP2016」蚯蚓-单调队列

本题中,我们将用符号 $\lfloor c \rfloor$ 表示对 $c$ 向下取整,例如: $\lfloor 3.0 \rfloor = \lfloor 3.1 \rfloor = \lfloor 3.9 \rfloor = 3$。
蛐蛐国最近蚯蚓成灾了!隔壁跳蚤国的跳蚤也拿蚯蚓们没办法,蛐蛐国王只好去请神刀手来帮他们消灭蚯蚓。
蛐蛐国里现在共有 $n$ 只蚯蚓( $n$ 为正整数)。每只蚯蚓拥有长度,我们设第 $i$ 只蚯蚓的长度为 $a_i$( $i = 1, 2, \ldots , n$),并保证所有的长度都是非负整数(即:可能存在长度为 $0$ 的蚯蚓)。
每一秒,神刀手会在所有的蚯蚓中,准确地找到最长的那一只(如有多个则任选一个)将其切成两半。神刀手切开蚯蚓的位置由常数 $p$(是满足 $0 < p < 1$ 的有理数)决定,设这只蚯蚓长度为 $x$,神刀手会将其切成两只长度分别为 $\lfloor px \rfloor$ 和 $x - \lfloor px \rfloor$ 的蚯蚓。特殊地,如果这两个数的其中一个等于 $0$,则这个长度为 $0$ 的蚯蚓也会被保留。此外,除了刚刚产生的两只新蚯蚓,其余蚯蚓的长度都会增加 $q$(是一个非负整常数)。
蛐蛐国王知道这样不是长久之计,因为蚯蚓不仅会越来越多,还会越来越长。蛐蛐国王决定求助于一位有着洪荒之力的神秘人物,但是救兵还需要 $m$ 秒才能到来 $\cdots \cdots$ ( $m$ 为非负整数)
蛐蛐国王希望知道这 $m$ 秒内的战况。具体来说,他希望知道:
$m$ 秒内,每一秒被切断的蚯蚓被切断前的长度(有 $m$ 个数);
$m$ 秒后,所有蚯蚓的长度(有 $n + m$ 个数)。
蛐蛐国王当然知道怎么做啦!但是他想考考你 $\cdots \cdots $

替罪羊树学习笔记[模板]

替罪羊树学习总结[模板]

传说中效率极高且较为好写的平衡树(抛开丧心病狂的红黑树和veb树),替罪羊树写法相当暴力,不用旋转,它只会选择性地重新构树来保证复杂度。

NOIP2016总结【游记】

NOIP2016总结【游记】

学$OI$也有半年了,第一次参加$noip$,感觉自己还是太弱了…各种不熟练…总之就是挂掉了…
不过毕竟高一,还有时间努力奋斗…
%%qy神犇 %%高二神犇 %%高三神犇

NOIP赛前总结

NOIP赛前总结

算法

基础算法

  • 模拟
  • 排序(注意合理使用 $sort$ 与 $stable_sort$ 及手写线性排序)
  • 贪心(注意对拍验证)
  • 分治
  • 递推
  • 二分答案(注意边界设定)
  • 逆序对(树状数组,注意是否需要离散化)
  • 中位数($nth_element$)
  • 离散化(效率$Hash > sort + unique +$ 指针扫$> sort + unique+lower_bound>set$)
  • 倍增法
  • 构造法(大胆猜想+写拍)
  • 三分答案

20161115测试总结

T1

文件名打错…
此题应打表找规律,我们可以发现原题就是求$\sum\limits_{k = 0}^{n}m^k=\frac{m^{n + 1}-1}{m-1}$,用费马小定理求逆元,快速幂计算就好了。

树链剖分学习总结

树链剖分学习总结

如果要在一棵树上进行路径的修改,求极值,求和,似乎线段树即可完成,实际上只用线段树并不能很好的做到,只有用一种高级的东西——树链剖分

概念

树链,就是树上的路径。剖分,就是把路径分类为重链轻链
size[v]表示以v为根的子树的节点数,depth[v]表示v的深度(根深度为1),top[v]表示v所在的链的顶端节点,father[v]表示v的父亲,son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子),w[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置。只要把这些东西求出来,就能用$O(logn)$的时间完成原问题中的操作。

树上操作总结

树上操作学习总结

储存

用邻接表储存。

1
2
3
4
5
6
7
8
9
10
const int MAXN = 10010;
struct Node {
int v, w;
Node(int v, int w) : v(v), w(w) {}
};
vector<Node> edge[MAXN];
inline void addEdge(int u, int v, int w) {
edge[u].push_back(Node(v, w));
edge[v].push_back(Node(u, v));
}

20161114测试总结

T1

此题不说正解,我们来说一说玄学乱搞…
考虑贪心,暴力枚举原始盒子里的球,然后找出操作后对应的球的位置,暴力枚举每个区间(注意要按顺序枚举),扩展区间,看是否能移动到对应位置即可。

20161112测试总结

T1

先判断负数个数的奇偶性,再处理能直接判断的情况,然后用 double 一乘一除判断就好了。
此题还可以用神奇的数学方法,我们可以把相乘看成 $log$ 相加,处理符号就好了。

20161111练习总结

T1

此题同codeforces460D
注意各种边界+判断…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#include <bits/stdc++.h>
using namespace std;
int main() {
long long l, r;
int k;
while (cin >> l >> r >> k) {
if (k >= 4) {
if (l % 2 && r - l + 1 >= 5) {
cout << 0 << "\n" << 4 << "\n" << l + 1 << " " << l + 2 << " " << l + 3 << " " << l + 4 << "\n";
continue;
}
else if (l % 2 == 0 && r - l + 1 >= 4) {
cout << "0\n4\n" << l << " " << l + 1 << " " << l + 2 << " " << l + 3 << "\n";
continue;
}
k = 3;
}
if (k == 3) {
long long c = 3LL, b = 2LL, a = 1LL;
int flag = 0;
while (1) {
if (c <= r && a >= l) {
flag = 1;
break;
}
if (c > r) break;
a = a << 1 | 1;
b = b << 1 | 1;
c = c << 1;
}
if (flag) {
cout << "0\n3\n" << a << " " << b << " " << c << "\n";
continue;
}
k = 2;
}
if (k == 2) {
int flag = 0;
for (long long i = l; i <= l + 1; i++) {
if (i % 2LL == 0 && i + 1LL <= r) {
flag = 1;
cout << "1\n2\n" << i << " " << i + 1LL << "\n";
}
}
if (!flag) {
if ((l ^ r) < l) cout << (l ^ r) << "\n" << 2 << "\n" << l << " " << r << "\n";
else cout << l << "\n1\n" << l << "\n";
}
}
if (k == 1) {
cout << l << "\n" << 1 << "\n" << l << "\n";;
continue;
}
}
return 0;
}

20161111测试总结

T1

此题考语文,注意题意的理解…
贪心,特判偶数串就行。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <bits/stdc++.h>
using namespace std;
int sum, cnt, k;
int main() {
int t, n;
cin >> t;
while (t--) {
cin >> n;
sum = cnt = 0;
for (int i = 1; i <= n; i++)
cin >> k, sum += k / 2, cnt += k % 2;
if (cnt) cout << 1 + (sum / cnt) * 2 << "\n";
else cout << sum * 2 << "\n";
}
return 0;
}

20161110练习总结

T1

贪心,排序后一次一次跳和尽可能多地跳就好…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#include <bits/stdc++.h>
using namespace std;
bool iosig;
char ch;
template<class T>
inline void read(T &x) {
x = 0, iosig = 0;
do {
ch = getchar();
if (ch == '-') iosig = 1;
} while (!isdigit(ch));
while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ '0'), ch = getchar();
}
int maxh, maxjump, minjump;
int n, deltah;
int h[1000010];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.in", "r", stdin);
#endif
read(n), read(deltah);
for (int i = 1; i <= n; i++)
read(h[i]);
sort(h + 1, h + n + 1);
for (int i = 1; i <= n; i++) {
if (h[i] - h[i - 1] <= deltah)
maxh = h[i], maxjump++;
else break;
}
register int cur = 0, pre = 0;
while (h[pre] < maxh) {
while (h[cur] - h[pre] <= deltah && cur <= n)
cur++;
pre = --cur;
minjump++;
}
cout << maxh << " " << maxjump << " " << minjump;
return 0;
}

20161110测试总结

今天的题跟昨天的画风不一样啊…

T1

不要作死手写链表!!!
编号,排序,恢复链表就好…

20161109测试总结

T1

神奇的平衡三进制…
不懂为什么要转成三进制(好慢)。
直接预处理 $3$ 的幂和幂的前缀和,那么当 $x < 0$ 时,先输出 $T$,当$x>0$时,先输出$1$,当 $x = 0$ 时直接输出 $0$。最高位最多为 $maxDigit = \left \lceil \log_3x \right \rceil$,我们可以与 $3^{maxDigit}-sum[maxDigit-1]$ 比较,然后调整 $maxDigit$,然后向前枚举每一位,确定每一位的值就好了。

KMP 算法学习笔记

KMP算法学习总结

KMP(Knuth-Morris-Pratt)是一种改进的字符串匹配算法,也是算法竞赛中常用的字符串匹配算法之一,它可以有效地利用失配信息来使得匹配全过程中不回溯,从而在线性时间内完成匹配。

20161108测试总结

T1

一眼看成博弈论…
这是一道数学题,很容易推出可以下棋的格子时固定的,$\gcd(a, b)$ 的倍数格子是可以被下到的,其他的都是下不到的。然后就没了。证明有 $\gcd(a, b) = \gcd(a, a - b) = \gcd(a, a + b)$ 然后题解表示脑补一下就好了…

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×