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

相关文章

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

计算数组的斜率,偏移,R2

模拟Excel中的R2的计算。         public bool fnCheckRear_R2(List<double[]> lRear, int iMinRear, int iMaxRear, ref double dR2)         {             bool bResult = true;             int n = 0;             dou

C# double[] 和Matlab数组MWArray[]转换

C# double[] 转换成MWArray[], 直接赋值就行             MWNumericArray[] ma = new MWNumericArray[4];             double[] dT = new double[] { 0 };             double[] dT1 = new double[] { 0,2 };

linux 下Time_wait过多问题解决

转自:http://blog.csdn.net/jaylong35/article/details/6605077 问题起因: 自己开发了一个服务器和客户端,通过短连接的方式来进行通讯,由于过于频繁的创建连接,导致系统连接数量被占用,不能及时释放。看了一下18888,当时吓到了。 现象: 1、外部机器不能正常连接SSH 2、内向外不能够正常的ping通过,域名也不能正常解析。

PHP7扩展开发之数组处理

前言 这次,我们将演示如何在PHP扩展中如何对数组进行处理。要实现的PHP代码如下: <?phpfunction array_concat ($arr, $prefix) {foreach($arr as $key => $val) {if (isset($prefix[$key]) && is_string($val) && is_string($prefix[$key])) {$arr[

Go 数组赋值问题

package mainimport "fmt"type Student struct {Name stringAge int}func main() {data := make(map[string]*Student)list := []Student{{Name:"a",Age:1},{Name:"b",Age:2},{Name:"c",Age:3},}// 错误 都指向了最后一个v// a

码蹄集部分题目(2024OJ赛9.4-9.8;线段树+树状数组)

1🐋🐋配对最小值(王者;树状数组) 时间限制:1秒 占用内存:64M 🐟题目思路 MT3065 配对最小值_哔哩哔哩_bilibili 🐟代码 #include<bits/stdc++.h> using namespace std;const int N=1e5+7;int a[N],b[N],c[N],n,q;struct QUERY{int l,r,id;}que