hdu3564(二分+线段树)
来源:互联网 发布:psp网络联机 编辑:程序博客网 时间:2024/05/21 05:59
Another LIS
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 936 Accepted Submission(s): 328
Problem Description
There is a sequence firstly empty. We begin to add number from 1 to N to the sequence, and every time we just add a single number to the sequence at a specific position. Now, we want to know length of the LIS (Longest Increasing Subsequence) after every time's add.
Input
An integer T (T <= 10), indicating there are T test cases.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
For every test case, an integer N (1 <= N <= 100000) comes first, then there are N numbers, the k-th number Xk means that we add number k at position Xk (0 <= Xk <= k-1).See hint for more details.
Output
For the k-th test case, first output "Case #k:" in a separate line, then followed N lines indicating the answer. Output a blank line after every test case.
Sample Input
130 0 2
Sample Output
Case #1:112HintIn the sample, we add three numbers to the sequence, and form three sequences.a. 1b. 2 1c. 2 1 3
Author
standy
Source
2010 ACM-ICPC Multi-University Training Contest(13)——Host by UESTC
Recommend
zhouzeyong
本题给定一个数的序列,其中a[i]表示在第a[i]个位置插入i。输入的位置是没有顺序的。因此不能用一般的方法模拟插入,时间复杂度O(n^2)。可以用线段树。设置线段树的节点信息包含一个num表示该区间[left,right]还有的空位个数。最后一个数插入的位置a[i]肯定就是正确的位置;然后倒数第二个考虑已插入的数……于是可得最终的序列。但题目的LIS是动态的,即在每次插入后计算输出。线段树很容易球的每个元素的真实位置。依题意,最终序列da[1-n]存放的是1-n的某个排序。da[i]表示元素i在第da[i]个位置。我们从i=1开始求LIS,求得的时对应下表的LIS,但与元素的LIS等价。于是我们要求的是da[]的LIS,可以用二分的方法求解,时间复杂度为O(N*log(N))。
#include<iostream>#include<cstdio>#include<cstring>using namespace std;//************************************************************//算法1的时间复杂度为O(N*log(N))const int MAXN=100000+100;int data[MAXN];//存放原始数据int MaxV[MAXN];//MaxV[i]存放长度为i的严格递增子序列的最大值的最小值int ans[MAXN];int da[MAXN];struct node {int left,right,num;//num此处灵活处理}tree[MAXN*4];//1.建立以left,right为左右边界,将数组da中元素存储在首地址从1开始的线段树tree的叶节点上void Build( int id,int left,int right){ tree[id].left=left; tree[id].right=right;tree[id].num=right-left+1;//此处灵活处理 if(left==right)return ; else {int mid =(left+right)>>1; Build(id<<1,left,mid); Build((id<<1)|1,mid+1,right); }}void Updata(int id,int pos,int val){ tree[id].num--; if(tree[id].left==tree[id].right) {da[val]=tree[id].left;//val表示第几次操作,da[】存储的位置 return ; }if(tree[id<<1].num>=pos) Updata(id<<1,pos,val); else Updata((id<<1)|1,pos-tree[id<<1].num,val);}//二分查找返回MaxV中大于等于x的组靠左的下标int BinaryResearch(int x,int len){int mid,low=1,high=len;while(low<=high){mid=(low+high)>>1;if(MaxV[mid]<x)low=mid+1;else high=mid-1;}return low;}//返回原序列中严格递增子序列的最长长度void LIS(int n){int i,len=0;for(i=1;i<=n;i++){if(i==0||da[i]>MaxV[len])//比长度为len的子序列最大值大,直接加进末尾MaxV[++len]=da[i];else {int pos=BinaryResearch(da[i],len);MaxV[pos]=da[i];}ans[i]=len;}}//===============================================int main(){int cas,i,n,tag=1;cin>>cas;while(cas--){scanf("%d",&n);for(i=1;i<=n;i++){scanf("%d",&data[i]);data[i]++;}Build(1,1,n);for(i=n;i>=1;i--){Updata(1,data[i],i);}LIS(n);printf("Case #%d:\n",tag++);for(i=1;i<=n;i++)printf("%d ",da[i]);printf("*******\n");for(i=1;i<=n;i++)printf("%d\n",ans[i]);printf("\n");}system("pause");return 0;}
- hdu3564(二分+线段树)
- HDU3564 线段树+dp
- HDU3564 Another LIS 线段树
- 【线段树】【LIS】Another Lis HDU3564 UESTC2010
- HDU3564:Another LIS(线段树单点+LIS)
- hdu3564 Another LIS (线段树处理后的裸LIS)
- HDU3564——Another LIS(线段树)
- hdu4614 二分+线段树
- hdu5217Brackets【线段树,二分】
- 【HDU4614】【线段树】【二分】
- HDU4791(线段树+二分)
- HDU5592(线段树+二分)
- Codeforces460C【二分+线段树】
- hdu6070 二分+线段树
- HDU6070 二分 线段树
- hdu6070 线段树+二分
- UVA12663 线段树+二分
- poj2182 线段树/线段数组+二分搜索
- eclipse快速生成java方法的注释
- 使用CentOS光盘镜像作为YUM源安装rpm软件包
- python judge prime number
- C++盲点
- QML文本中实现网页超链接
- hdu3564(二分+线段树)
- 亿能测试白盒安全测试模板V1.0发布
- 算法竞赛入门经典P89 卡片游戏
- Shell中的if else语句小演示
- Entity Framework系列文章导航
- java.math.BigDecimal类的用法
- 数据库优化小计
- 算法竞赛入门经典P91铁轨
- Eclipse中设置编码的方式