2019HDU多校第六场——HDU6635 Nonsense Time【树状数组求LIS】

2023-12-31 22:40

本文主要是介绍2019HDU多校第六场——HDU6635 Nonsense Time【树状数组求LIS】,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

题目链接: HDU6635 Nonsense Time

Time Limit: 14000/14000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java/Others)

Problem Description

You a given a permutation p1,p2,…,pn of size n. Initially, all elements in p are frozen. There will be n stages that these elements will become available one by one. On stage i, the element pki will become available.

For each i, find the longest increasing subsequence among available elements after the first i stages.

Input

The first line of the input contains an integer T(1≤T≤3), denoting the number of test cases.

In each test case, there is one integer n(1≤n≤50000) in the first line, denoting the size of permutation.

In the second line, there are n distinct integers p1,p2,...,pn(1≤pi≤n), denoting the permutation.

In the third line, there are n distinct integers k1,k2,...,kn(1≤ki≤n), describing each stage.

It is guaranteed that p1,p2,...,pn and k1,k2,...,kn are generated randomly.

Output

For each test case, print a single line containing n integers, where the i-th integer denotes the length of the longest increasing subsequence among available elements after the first i stages.

Sample Input

1

5

2 5 3 1 4

1 4 5 3 2

Sample Output

1 1 2 3 3

题意:

给你一个1~n的排列a和排列b,起始状态a中所有数都是冻结的,i时刻a中b[i]这个数解冻,计算出当前a中已解冻的数的最长上升子序列。

分析:

正难则反,考虑倒着处理,按照b倒序冻结a中的数;

第n个时刻所有数都已解冻,树状数组求出当前的LIS并标记当前构成LIS,然后向前更新,如果当前冻结的数不在LIS中,那么不改变,否则再次求解LIS;

可以证明,这样的时间复杂度是O(n\sqrt{n}logn)

Tips:类似链表的方式记录前后指针,给原序列加上前后端点,这样就可以快速的得到冻结某个数之后的序列。

#include<bits/stdc++.h>
using namespace std;
const int maxn=5e4+7;
int a[maxn],b[maxn],vis[maxn],tag[maxn];
int LIS[maxn],bit[maxn],pre[maxn],nxt[maxn],ans[maxn];
int n;
int lowbit(int x) {return x&-x;}
void getLIS()
{for (int i=nxt[0];i<=n+1;i=nxt[i]){vis[i]=0;int tmp=0,res=a[i];while (res){if(LIS[tmp]<LIS[bit[res]]) tmp=bit[res];res-=lowbit(res);}LIS[i]=LIS[tmp]+1;tag[i]=tmp;res=a[i];while (res<=n+2){if(LIS[bit[res]]<LIS[i]) bit[res]=i;res+=lowbit(res);}}for (int i=nxt[0];i<=n+1;i=nxt[i]){int res=a[i];while (res<=n+2){bit[res]=0;res+=lowbit(res);}}for (int i=n+1;i;i=tag[i]) vis[i]=1;
}
void rua()
{scanf("%d",&n);for (int i=1;i<=n;i++) scanf("%d",&a[i]),a[i]++;a[0]=1;a[n+1]=n+2;for (int i=0;i<=n+1;i++) {pre[i]=i-1;nxt[i]=i+1;vis[i]=bit[i]=0;}bit[n+2]=0;for (int i=1;i<=n;i++) scanf("%d",&b[i]);getLIS();for (int i=n;i;i--){ans[i]=LIS[n+1]-1;int x=b[i];pre[nxt[x]]=pre[x];nxt[pre[x]]=nxt[x];if(vis[x]) getLIS();}for (int i=1;i<n;i++) printf("%d ",ans[i]);printf("%d\n",ans[n]);	
}
int main()
{int t;scanf("%d",&t);while (t--) rua();return 0;
}

 

这篇关于2019HDU多校第六场——HDU6635 Nonsense Time【树状数组求LIS】的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/557333

相关文章

MySQL中时区参数time_zone解读

《MySQL中时区参数time_zone解读》MySQL时区参数time_zone用于控制系统函数和字段的DEFAULTCURRENT_TIMESTAMP属性,修改时区可能会影响timestamp类型... 目录前言1.时区参数影响2.如何设置3.字段类型选择总结前言mysql 时区参数 time_zon

Java 字符数组转字符串的常用方法

《Java字符数组转字符串的常用方法》文章总结了在Java中将字符数组转换为字符串的几种常用方法,包括使用String构造函数、String.valueOf()方法、StringBuilder以及A... 目录1. 使用String构造函数1.1 基本转换方法1.2 注意事项2. 使用String.valu

Python 标准库time时间的访问和转换问题小结

《Python标准库time时间的访问和转换问题小结》time模块为Python提供了处理时间和日期的多种功能,适用于多种与时间相关的场景,包括获取当前时间、格式化时间、暂停程序执行、计算程序运行时... 目录模块介绍使用场景主要类主要函数 - time()- sleep()- localtime()- g

JAVA中整型数组、字符串数组、整型数和字符串 的创建与转换的方法

《JAVA中整型数组、字符串数组、整型数和字符串的创建与转换的方法》本文介绍了Java中字符串、字符数组和整型数组的创建方法,以及它们之间的转换方法,还详细讲解了字符串中的一些常用方法,如index... 目录一、字符串、字符数组和整型数组的创建1、字符串的创建方法1.1 通过引用字符数组来创建字符串1.2

如何使用 Bash 脚本中的time命令来统计命令执行时间(中英双语)

《如何使用Bash脚本中的time命令来统计命令执行时间(中英双语)》本文介绍了如何在Bash脚本中使用`time`命令来测量命令执行时间,包括`real`、`user`和`sys`三个时间指标,... 使用 Bash 脚本中的 time 命令来统计命令执行时间在日常的开发和运维过程中,性能监控和优化是不

vue如何监听对象或者数组某个属性的变化详解

《vue如何监听对象或者数组某个属性的变化详解》这篇文章主要给大家介绍了关于vue如何监听对象或者数组某个属性的变化,在Vue.js中可以通过watch监听属性变化并动态修改其他属性的值,watch通... 目录前言用watch监听深度监听使用计算属性watch和计算属性的区别在vue 3中使用watchE

hdu2241(二分+合并数组)

题意:判断是否存在a+b+c = x,a,b,c分别属于集合A,B,C 如果用暴力会超时,所以这里用到了数组合并,将b,c数组合并成d,d数组存的是b,c数组元素的和,然后对d数组进行二分就可以了 代码如下(附注释): #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<que

hdu 1166 敌兵布阵(树状数组 or 线段树)

题意是求一个线段的和,在线段上可以进行加减的修改。 树状数组的模板题。 代码: #include <stdio.h>#include <string.h>const int maxn = 50000 + 1;int c[maxn];int n;int lowbit(int x){return x & -x;}void add(int x, int num){while

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou