[2019杭电多校第六场][hdu6635]Nonsense Time

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6635

题意是说一开始所有数都冻结,第i秒会解冻第ki个数,求每秒状态下的最长上上升子序列长度。

这种题一想添加操作就不好实现,所以干脆反着来,想删除操作。

从第n秒开始往前遍历,每次都会冻结一个数,这时判断一下这个数是否一定要在最长上升子序列里。

使用二分的方法求最长上升子序列,并且每次求完子序列后可以处理出那些位置是必须在最长上升子序列里的。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<string>
 5 #include<algorithm>
 6 #include<queue>
 7 using namespace std;
 8 const int maxn = 5e4 + 10;
 9 int a[maxn], vis[maxn], ans[maxn], d[maxn], in[maxn], dp[maxn];
10 int len;
11 void  slove(int n) {
12     len = 0;
13     for (int i = 1; i <= n; i++) {
14         if (a[i] != 0) {
15             int pos = lower_bound(d + 1, d + 1 + len, a[i]) - d;
16             if (pos > len)
17                 d[++len] = a[i];
18             else
19                 d[pos] = a[i];
20             dp[i] = pos;
21         }
22     }
23     int q = len, limit = n;
24     for (int i = n; i >= 1; i--) {
25         if (dp[i] == q && a[i] <= limit && a[i] != 0) {
26             limit = a[i];
27             in[i] = 1;
28             q--;
29         }
30         else
31             in[i] = 0;
32     }
33 }
34 int main() {
35     int t;
36     scanf("%d", &t);
37     while (t--) {
38         int n;
39         scanf("%d", &n);
40         for (int i = 1; i <= n; i++)
41             scanf("%d", &a[i]);
42         for (int i = 1; i <= n; i++)
43             scanf("%d", &vis[i]);
44         slove(n);
45         for (int i = n; i >= 1; i--) {
46             ans[i] = len;
47             a[vis[i]] = 0;
48             if (in[vis[i]])slove(n);
49         }
50         for (int i = 1; i <= n; i++)
51             printf("%d%c", ans[i], i == n ? ‘\n‘ : ‘ ‘);
52     }
53 }

原文地址:https://www.cnblogs.com/sainsist/p/11379494.html

时间: 2024-08-02 12:35:51

[2019杭电多校第六场][hdu6635]Nonsense Time的相关文章

2019 杭电多校 第六场

2019 Multi-University Training Contest 6 补题链接:2019 Multi-University Training Contest 6 1002 Nonsense Time (HDU 6635) 题意 给定包含 \(n\) 个不同数字的排列 \(p\).一开始所有数字都冻住.再给出一个长度为 \(n\) 的数组 \(k\),\(k[i]\) 表示 \(p[k[i]]\) 在第 \(i\) 时刻解冻.输出 \(n\) 个数,表示第 \(i\) 个时刻数组 \(

2019杭电多校第六场hdu6638 Snowy Smile(线段树+枚举)

Snowy Smile 题目传送门 解题思路 先把y离散化,然后把点按照x的大小进行排序,我们枚举每一种x作为上边界,然后再枚举其对应的每一种下边界.按照这种顺序插入点,这是一个压维的操作,即在线段树中的y位置加上其w,并利用线段树来更新动态的最大子段和. 代码如下 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; const int N = 2005; stru

2019 杭电多校 第五场

2019 Multi-University Training Contest 5 补题链接:2019 Multi-University Training Contest 5 罚时爆炸 自闭场 1004 equation (HDU 6627) 题意: 给定一个整数 \(C\) 和 \(N\) 组 \(a_i,b_i\),求 \(∑_{i=1}^N|a_i\cdot x + b_i| = C\) 的所有解,如果有无穷多个解就输出 -1. 思路 分类讨论 分类讨论去绝对值.根据 \(b_i / a_i

2019 杭电多校 第八场

2019 Multi-University Training Contest 8 补题链接:2019 Multi-University Training Contest 8 1003 Acesrc and Good Numbers HDU 6659 题意 定义 \(f(d, n)\) 为十进制下 \(1\) 到 \(n\) 所有数的数位中数字 \(d\) 出现的次数.给定 \(x\),找出最大的 \(n(n \le x)\) 满足 \(f(d, n) = n\). 题解 看到了一个神仙做法. 显

2019 杭电多校 第七场

2019 Multi-University Training Contest 7 补题链接:2019 Multi-University Training Contest 7 1001 A + B = C 题意: 给出 \(a, b, c\),求 \(x, y, z\) 满足 \(a\cdot 10^x + b\cdot 10^y = c\cdot 10^z\).\(a, b, c \le 10^{100000}\). 题解: 补零到 \(a, b, c\) 长度相等之后,可能的情况只有四种: \

2019 杭电多校 第四场

2019 Multi-University Training Contest 4 补题链接:2019 Multi-University Training Contest 4 1001 AND Minimum Spanning Tree (HDU 6614) 题意 给定一个有 \(N\) 个结点的完全图,编号从 \(1\) 到 \(N\).结点 \(x\) 与结点 \(y\) \((1\leq x, y\leq N, x \neq y)\) 的边的权值为 \(x\) 与 \(y\) 按位与的值,求

2019 杭电多校 第三场

2019 Multi-University Training Contest 3 补题链接:2019 Multi-University Training Contest 3 1002 Blow up the city (HDU-6604) 题意 给定 \(n\) 个点和 \(m\) 条边的有向无环图,给出 \(q\) 次询问,每个询问给出 \(a\) 和 \(b\),求有多少个点,满足该点删去后 \(a\) 和 \(b\) 中至少一个点不能到达出度为 \(0\) 的点. 题解 支配树/灭绝树 拓

2019杭电多校第三场 1004 Distribution of books

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6606 考虑二分答案,我们二分一个值\(x\),那么要怎么来验证这个答案是否可行,考虑dp求解,设\(dp[i]\)为前i个在答案为\(x\)的情况下划分最最多组数,那么若\(dp[n] \geq k\) 则这个x可行, 很显然可以看出\(x\)是单调的,所以二分. \[dp[i] = max(dp[j]) + 1 (sum[i] - sum[j-1] \leq x)\] 如果直接采用暴力枚举的话复杂

2019杭电多校第四场hdu6621 K-th Closest Distance(二分答案+主席树)

K-th Closest Distance 题目传送门 解题思路 二分答案+主席树 先建主席树,然后二分答案mid,在l和r的区间内查询[p-mid, p+mid]的范围内的数的个数,如果大于k则说明这个范围内存在第k小的数,r=mid,否则不存在,l=mid+1. 代码如下 #include <bits/stdc++.h> #define INF 0x3f3f3f3f using namespace std; typedef long long ll; inline int read(){