T1 seq
【问题描述】
给一个长度为 ? 的序列 ? ,你可以把 ? 中的 0 改成其他的数字.
(正数,负数, 0均可,不同的 0 可以改成不同的而数字),
要求修改后 ? 最长上升子序列的长度最大.输出这个长度.
【输入格式】
第一行一个 ? ,表示数字的个数.
接下来 ? 个数字,第 ? 个表示 ??.
【输出格式】
一个数字,答案.
【数据规模】
对于 20% 的数据, ? ≤ 20, ?? ≥ 1 .
对于 60% 的数据, ? ≤ 1000 .
对于另 10% 的数据, ?? ≤ 10 .
对于 100% 的数据, ? ≤ 10^5, 0 ≤ ?? ≤ 10^9.
【题目解答】
题意为:给一个序列,你可以把序列中的 0 随意修改,要求最大化 LIS 的长度.
记 ?? 表示前 ? 个数字中 0 的个数,可以写出一个很显然的 dp.
??[?]= max (?<?,??<??) { ??[?] + min{ ?? − ?? − 1, ?? − ?? } }。
时间复杂度 ?(?^2) .使用数据结构可以做到 ?(? log2? ).
然后只需注意到一定存在一种最优解使得所有的 0 都被加了进来,
所以 0 的个数加上对所有非 0 数的 ?? − ?? 算 LIS 的长度就是答案.
时间复杂度 ?(? log ? ) .
#include <cmath> #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <vector> #include <algorithm> #include <stack> #include <queue> #include <deque> using namespace std; typedef long long ll; typedef unsigned long long ull; /*【seq】 给一个长度为?的序列?,可以把0改成其他的数字。 -----> 正数,负数,0均可,不同的0可以改成不同的数字。 要求修改后?最长上升子序列的长度最大。输出这个长度。 */ deque<int> dq; //双端队列:支持在两端高效地插入删除元素的连续线性存储空间 int main(){ int n,num0=0; cin >> n; dq.push_front(INT_MIN); //队头初始化为-inf for(int i = 0; i < n; i++) { int t; cin >> t; if(t == 0) { num0++; dq.push_front(INT_MIN); } else{ int cnt=lower_bound(dq.begin(),dq.end(),t-num0)-dq.begin()-1; int best=cnt+1; if(best==dq.size()) dq.push_back(INT_MAX); dq[best]=min(dq[best],t-num0); } } cout << dq.size()-1 << endl; return 0; }
T2 paint
【问题描述】
给出一张 ? 个点, ? 条边的图 ?(?, ? ) ,点的标号是 0 到 ? − 1 .
对于每个非空点集 ? (共有 2^?−1 个),
定义 ? (? ) = min{?|?存在? −染色方案},要求对每个 ? 都计算 ? (? ) .
定义一个点集 ? 的 ?−染色方案是指对所有的 ? ∈ ? 确定一个 ?? ∈ [1, ? ] ,
使得所有 ? ∈ ?, ? ∈ ?, (?, ?) ∈ ? 的点对 (?, ?) 有 ?? != ??.
【输入格式】
第一行一个数 ? ,表示点数.
接下来 ? 行,每行一个长度为 ? 的 01 串,表示邻接矩阵.
数据保证合法.
【输出格式】
一个数字,答案.
【数据规模】
对于 30% 的数据, ? ≤ 4 .
对于 60% 的数据, ? ≤ 10 .
对于 100% 的数据, ? ≤ 18 .
【题目解答】
给一张无向图,要求对于每个非空点集都计算色数.? ≤ 18.
T3 trie
【问题描述】
有 ? 个串,有 ? 个询问,每次询问用 ?, ? 描述,
表示询问编号在 [?, ?] 中的串有多少个不同的前缀.
【输入格式】
第一行一个数字 ? ,表示串的个数.
接下来 ? 行,每行一个串.
接下来一个 ? ,表示询问次数.
接下来 ? 行,每行两个数 ?0, ?0,表示询问区间,
为了强制在线,你需要做以下操作:
? = (?0 + ???????) ??? ? + 1
? = (?0 + ???????) ??? ? + 1
?? ( ? > ? ) ????( ? , ? )
??????? 表示上一次询问的答案,初始为 0 .
【输出格式】
? 行,每行一个数表示答案.
【数据规模】
【题目解答】
有 ? 个串,有 ? 次询问,每次把一个区间里的串插到 trie 里,问有多少个节点.
算法一
把所有的串拉进去建一个 trie ,每次询问就变成求关键点到根路径并的大小,
把关键点按照 dfs 排序后就变成深度和减排序后相邻两点 lca 的深度和.
考虑维护后者,把序列分块,处理出块到块之间后者的值,
这个可以用主席树解决,询问也类似.
时间复杂度 ?((? + ?)√? log ? ) ,期望得分 70 分.
算法二
把序列的前缀 hash 以后排成一排,
问题就变成了区间 [?, ?] 中有多少个不同的数字.
用 ??? ? 表示 ? 前面一个和 ?? 相同的位置,
问题就变成求 ??? ? < ?, ? ≤ ? ≤ ?的 ? 的个数,
这是一个二维数点问题,直接主席树即可.
——时间划过风的轨迹,那个少年,还在等你。