【浮*光】 #noip模拟# 2018.08.29

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 以后排成一排,

问题就变成了区间 [?, ?] 中有多少个不同的数字.

用 ??? ? 表示 ? 前面一个和 ?? 相同的位置,

问题就变成求 ??? ? < ?, ? ≤ ? ≤ ?的 ? 的个数,

这是一个二维数点问题,直接主席树即可.

 

 

                                               ——时间划过风的轨迹,那个少年,还在等你。

 

转载于:https://www.cnblogs.com/FloraLOVERyuuji/p/9554951.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值