hdu-5489(2015网络赛合肥赛区)***
2015-09-30 19:34
411 查看
题目链接
题意:给定一个长度为N<=105的序列
求删去连续长度为0<=L<=N的序列后的LIS
思路:
假设你已经会O(nlogn)的LIS, 删去i
前面连续一段长度为L
即[i−L,i-1]的
序列, 左边是i−L−1,
右边是i,
求剩下的LIS
首先预处理出:
f[i]:=以a[i]结尾的LIS的最大长度
g[i]:=以a[i]开头的LIS的最大长度
我们可以根据i,
找到 [0,i−L−1]之间的一个值
其值小于a[i],
而其f[i]值是最大的,
也就是O(n2)求LIS的思想
关键是如何快速确定在[0,i−L−1]中,
找到这个值
我们利用线段树和离散化, 将a[i]映射到线段树上
假设i位置对应的值是x,并且其映射到线段树上对应的下标是y
那么我们只要在线段树上查找[0,y−1]之间的最大值maxv
maxv[i]=max{f[j],j∈[0,i−L+1]∪a[j]<a[i]}
其实就是dp[i]:=以a[i]结尾,
删去[i−L,i−1]长度为L的LIS的最大长度
dp[i]=maxv[i]+g[i],ans=max{dp[i]}
注意:普通的LIS算法只能求得区间内的LIS但不能保证毕包含头或尾,
这里利用lower_bound函数在nlogn的时间求任意前缀且包含前缀尾的LIS ( 即f[ i ] )。
同样利用该函数求得任意后缀且包含后缀头的LIS ( 即g[ i ] )。
题意:给定一个长度为N<=105的序列
求删去连续长度为0<=L<=N的序列后的LIS
思路:
假设你已经会O(nlogn)的LIS, 删去i
前面连续一段长度为L
即[i−L,i-1]的
序列, 左边是i−L−1,
右边是i,
求剩下的LIS
首先预处理出:
f[i]:=以a[i]结尾的LIS的最大长度
g[i]:=以a[i]开头的LIS的最大长度
我们可以根据i,
找到 [0,i−L−1]之间的一个值
其值小于a[i],
而其f[i]值是最大的,
也就是O(n2)求LIS的思想
关键是如何快速确定在[0,i−L−1]中,
找到这个值
我们利用线段树和离散化, 将a[i]映射到线段树上
假设i位置对应的值是x,并且其映射到线段树上对应的下标是y
那么我们只要在线段树上查找[0,y−1]之间的最大值maxv
maxv[i]=max{f[j],j∈[0,i−L+1]∪a[j]<a[i]}
其实就是dp[i]:=以a[i]结尾,
删去[i−L,i−1]长度为L的LIS的最大长度
dp[i]=maxv[i]+g[i],ans=max{dp[i]}
注意:普通的LIS算法只能求得区间内的LIS但不能保证毕包含头或尾,
这里利用lower_bound函数在nlogn的时间求任意前缀且包含前缀尾的LIS ( 即f[ i ] )。
同样利用该函数求得任意后缀且包含后缀头的LIS ( 即g[ i ] )。
#pragma comment(linker, "/STACK:102400000,102400000") #include<iostream> #include<stdio.h> #include<math.h> #include <string> #include<string.h> #include<map> #include<queue> #include<set> #include<utility> #include<vector> #include<algorithm> #include<stdlib.h> using namespace std; #define eps 1e-8 #define pii pair<int,int> #define inf 0x3f3f3f3f #define rd(x) scanf("%d",&x) #define rd2(x,y) scanf("%d%d",&x,&y) #define ll long long int #define mod 1000003 #define maxn 110000 #define maxm 10001005 int mi(int a,int b){return a<b?a:b;} int ma(int a,int b){return a>b?a:b;} int n,t,L,ans; int a[maxn],aa[maxn]; int f[maxn],g[maxn],h[maxn]; int mx[maxn*4]; void update(int rt,int x,int v,int l,int r){ if(l==r) { mx[rt]=ma(mx[rt],v); return; } int mid=(l+r)>>1; if(mid>=x) update(rt*2,x,v,l,mid); else update(rt*2+1,x,v,mid+1,r); mx[rt]=ma(mx[rt*2],mx[rt*2+1]); } int query(int rt,int lx,int rx,int l,int r){ if(l==lx&&r==rx) return mx[rt]; int mid=(l+r)>>1; if(rx<=mid) return query(rt*2,lx,rx,l,mid); else if(lx>mid) return query(rt*2+1,lx,rx,mid+1,r); else { int lv=query(rt*2,lx,mid,l,mid); int rv=query(rt*2+1,mid+1,rx,mid+1,r); return ma(lv,rv); } } int main() { rd(t); int tt=0; while(t--){ rd2(n,L); for(int i=1;i<=n;i++){ rd(a[i]); aa[i]=a[i]; } sort(aa+1,aa+1+n); int nn=unique(aa+1,aa+1+n)-aa-1; memset(h,0x3f,sizeof h); for(int i=1;i<=n;i++){//求1~i的包含a[i]的LIS!! int k=lower_bound(h+1,h+1+n,a[i])-h; f[i]=k; h[k]=a[i]; } memset(h,0x3f,sizeof h); for(int i=n;i>=1;i--){//求i~n的包含a[i]的LIS!! int k=lower_bound(h+1,h+1+n,-a[i])-h; g[i]=k; h[k]=-a[i]; } a[0]=f[0]=g[n+1]=0; a[n+1]=0x3f3f3f3f; memset(mx,0,sizeof mx); ans=0; for(int i=L+1;i<=n+1;i++){ int k=lower_bound(aa+1,aa+1+nn,a[i])-aa; int v=query(1,0,k-1,0,nn); ans=ma(ans,v+g[i]); k=lower_bound(aa+1,aa+1+nn,a[i-L])-aa; if(i<=n) update(1,k,f[i-L],0,nn); } printf("Case #%d: %d\n",++tt,ans); } return 0; }
相关文章推荐
- 浅谈C#网络编程(二)
- 【重量级】揭秘移动网络的性能(在)--移动网络组件具体解释
- BP神经网络从理论到应用(一):C++实现
- ipconfig 查看IP和网络查看IP不同之处
- 《图解HTTP》读书笔记
- 网络请求框架-Volley
- Windows10更改网络类型-公用-专用
- Android网络编程随想录(四)
- poj 1273 Drainage Ditches (网络流 最大流)
- ios9 http问题
- 浅谈网络编程的入门
- MPMoviePlayerViewController播放网络视频bug
- 《TCP/IP详解 卷一:协议》读书笔记--概述
- Unix网络
- 【网络】——计算机网络
- uc笔记10---网络通信,套接字(Socket),基于 TCP 协议的客户机/服务器模型
- 云计算中心网络资源分配-Faircloud: sharing the network in cloud computing
- 通过HTTP RESTful API 操作elasticsearch搜索数据
- 解析TCP/UDP协议的通讯软件
- android-async-http AsyncHttpClient介绍