HDU_5141 LIS again[线段树]
2014-12-10 23:41
211 查看
传送门:HUD_5141
A numeric sequence of ai is ordered if
a1<a2<…<aN.
Let the subsequence of the given numeric sequence (a1,a2,…,aN)
be any sequence (ai1,ai2,…,aiK),
where 1≤i1<i2<…<iK≤N.
For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others.
S[ i , j ] indicates ( ai,ai+1,ai+2,…,aj)
.
Your program, when given the numeric sequence (a1,a2,…,aN),
must find the number of pair ( i, j) which makes the length of the longest ordered subsequence of S[ i , j ] equals to the length of the longest ordered subsequence of (a1,a2,…,aN).
[align=left]Input[/align]
Multi test cases (about 100), every case occupies two lines, the first line contain n, then second line contain n numbersa1,a2,…,aN
separated by exact one space.
Process to the end of file.
[Technical Specification]
1≤n≤100000
0≤ai≤1000000000
[align=left]Output[/align]
For each case,.output the answer in a single line.
[align=left]Sample Input[/align]
3
1 2 3
2
2 1
[align=left]Sample Output[/align]
1
3
题意:给你一串数列,其最长递增序列为lis,统计递增序列长度等于lis的区间的数目。
思路:线段树维护以i结尾的最长递增序列,且要求起点尽量靠右。
代码:
LIS again
[align=left]Problem Description[/align]A numeric sequence of ai is ordered if
a1<a2<…<aN.
Let the subsequence of the given numeric sequence (a1,a2,…,aN)
be any sequence (ai1,ai2,…,aiK),
where 1≤i1<i2<…<iK≤N.
For example, sequence (1, 7, 3, 5, 9, 4, 8) has ordered subsequences, eg. (1, 7), (3, 4, 8) and many others.
S[ i , j ] indicates ( ai,ai+1,ai+2,…,aj)
.
Your program, when given the numeric sequence (a1,a2,…,aN),
must find the number of pair ( i, j) which makes the length of the longest ordered subsequence of S[ i , j ] equals to the length of the longest ordered subsequence of (a1,a2,…,aN).
[align=left]Input[/align]
Multi test cases (about 100), every case occupies two lines, the first line contain n, then second line contain n numbersa1,a2,…,aN
separated by exact one space.
Process to the end of file.
[Technical Specification]
1≤n≤100000
0≤ai≤1000000000
[align=left]Output[/align]
For each case,.output the answer in a single line.
[align=left]Sample Input[/align]
3
1 2 3
2
2 1
[align=left]Sample Output[/align]
1
3
题意:给你一串数列,其最长递增序列为lis,统计递增序列长度等于lis的区间的数目。
思路:线段树维护以i结尾的最长递增序列,且要求起点尽量靠右。
代码:
#include<iostream> #include<cstring> #include<cstdio> #include<algorithm> #define ls(p) p<<1 #define rs(p) p<<1|1 using namespace std; typedef long long LL; const int N=100010; int a ,b ; int dp ; int sta ,en ; int len,st; struct node{ int l,r; int len,sta; }tree[N<<2]; void pushup(int p) { if(tree[ls(p)].len>tree[rs(p)].len) { tree[p].len=tree[ls(p)].len; tree[p].sta=tree[ls(p)].sta; } else if(tree[rs(p)].len>tree[ls(p)].len) { tree[p].len=tree[rs(p)].len; tree[p].sta=tree[rs(p)].sta; } else tree[p].sta=max(tree[ls(p)].sta,tree[rs(p)].sta); } void build(int p,int l,int r) { tree[p].l=l;tree[p].r=r; tree[p].len=-1; tree[p].sta=-1; if(l==r) return; int m=(l+r)>>1; build(ls(p),l,m); build(rs(p),m+1,r); } void update(int p,int pos,int len,int st) { if(tree[p].l==tree[p].r) { if(tree[p].len==len&&tree[p].sta<st) tree[p].sta=st; else if(tree[p].len<len) { tree[p].len=len; tree[p].sta=st; } return; } int m=(tree[p].l+tree[p].r)>>1; if(pos<=m) update(ls(p),pos,len,st); else update(rs(p),pos,len,st); pushup(p); } void query(int p,int l,int r) { if(l<=tree[p].l&&tree[p].r<=r) { if(tree[p].len>len) { len=tree[p].len; st=tree[p].sta; } else if(tree[p].len==len&&st<tree[p].sta) st=tree[p].sta; return; } int m=(tree[p].l+tree[p].r)>>1; if(l<=m) query(ls(p),l,r); if(r>m) query(rs(p),l,r); } int main() { int n; while(scanf("%d",&n)==1) { LL ret=0; int cnt; for(int i=1;i<=n;i++) { scanf("%d",a+i); b[i]=a[i]; } if(n==1) { printf("1\n"); continue; } sort(b+1,b+1+n); cnt=unique(b+1,b+1+n)-(b+1); dp[1]=sta[1]=1; build(1,1,cnt); int mpp; int lest=-1; for(int i=1;i<=n;i++) { len=st=-1; mpp=lower_bound(b+1,b+1+cnt,a[i])-b; if(mpp==1) { dp[i]=1; sta[i]=i; } else query(1,1,mpp-1); if(st==-1) { dp[i]=1; sta[i]=i; } else { dp[i]=len+1; sta[i]=st; } //cout<<mpp<<dp[i]<<sta[i]<<"--\n"; update(1,mpp,dp[i],sta[i]); lest=max(lest,dp[i]); } int last=n+1; for(int i=n;i>=1;i--) { if(dp[i]==lest) { en[i]=last-1; last=i; } } for (int i=1;i<=n;++i) { if (dp[i]==lest) ret+=(LL)sta[i]*(LL)(en[i]-i+1); } printf("%I64d\n", ret); } return 0; }
相关文章推荐
- HDU 5141 LIS again(dp+线段树)
- 【HDU】5141 LIS again 在普通nlogn求LIS的基础上稍作修改
- HDU 5141 LIS Again LIS变形+BIT
- hdu_3564_Another LIS(线段树+LIS)
- hdu_3564_Another LIS(线段树+LIS)
- HDU 4419 Colourful Rectangle 线段树求矩阵的并升级版again
- hdu 5489 Removed Interval(线段树+LIS)
- hdu 3564(线段树+LIS)
- hdu 3564 Another LIS(线段树+lis)
- HDOJ 5141 LIS again 二分
- hdu 1257 一共要多少套拦截系统 (LIS)
- Hdu 2795 线段树的运用
- hdu 5239 区间平方 线段树区间更新
- hdu 4117 GRE Words (AC自动机+线段树)
- hdu 3255 Farming(线段树求长方体体积并)
- hdu 5107 K-short Problem(线段树)
- HDU -1754线段树
- HDU 1394 Minimum Inversion Number 线段树和逆序数的应用
- HDU 4553 约会安排 (线段树 -- 区间合并(多种优先级的区间合并) )
- HDU 1789 Doing Homework again!