bzoj3173 最长上升子序列 树状数组

链接:http://www.lydsy.com/JudgeOnline/problem.php?id=3173

题意:向序列中动态插入$1~n$排列元素,求出插入每个元素后最长上升子序列长度。

如Claris所言,面对这种数据结构,必有高论。如果只想着数据结构,我们可以通过平衡树动态维护序列,同时使用树状数组计算最长上升子序列。

但是我们不是猩猩不是数据结构狂人,我们毕竟还是要本着能不上树就不上树能少用数据结构就少用的原则来设计算法的。

重新考虑这个题目。本题没有要求强制在线,于是我们把整个操作倒过来看,于是问题就变成了不停地删去序列中某个元素后求出当前最长上升子序列长度。

然后,不要忘了一个重要条件:这个东西是从小到大插入的。

从小到大插入,意味着插入一个数之后最长上升子序列发生变化的唯一可能就是以这个数结尾。

那么我们就维护一下删掉每个数之前以这个数结尾的最长上升子序列就好了,最后输出答案时,将这个与前一个比较,短就直接将当前这个数赋值成为上一个。

说得简单……但是这道题真的是一个树状数组综合运用……具体看代码吧……

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 using namespace std;
 6 int lowbit(int x)
 7 {
 8     return x&(-x);
 9 }
10 const int maxn=100005;
11 int C[maxn],n;
12 void Modify(int pos,int val)
13 {
14     for(;pos<=n;pos+=lowbit(pos))C[pos]+=val;
15 }
16 void Maximum(int pos,int val)
17 {
18     for(;pos<=n;pos+=lowbit(pos))C[pos]=max(C[pos],val);
19 }
20 int Query_kth(int k)
21 {
22     int cnt=0,ans=0;
23     for(int i=17;~i;i--)
24     {
25         ans+=(1<<i);
26         if(ans>=n||cnt+C[ans]>=k)ans-=(1<<i);
27         else cnt+=C[ans];
28     }
29     return ans+1;
30 }
31 int Query_max(int pos)
32 {
33     int res=0;
34     for(;pos;pos-=lowbit(pos))res=max(res,C[pos]);
35     return res;
36 }
37 int a[maxn],b[maxn],f[maxn];
38 int haha()
39 {
40     scanf("%d",&n);
41     for(int i=1;i<=n;i++)
42     {
43         scanf("%d",&a[i]);C[i]++;
44         if((i+lowbit(i))<=n)C[i+lowbit(i)]+=C[i];
45     }
46     int tmp;
47     for(int i=n;i;i--)b[tmp=Query_kth(a[i]+1)]=i,Modify(tmp,-1);
48     memset(C,0,sizeof(C));
49     for(int i=1;i<=n;i++)f[b[i]]=Query_max(b[i])+1,Maximum(b[i],f[b[i]]);
50     for(int i=1;i<=n;i++)printf("%d\n",f[i]<f[i-1]?(f[i]=f[i-1]):f[i]);
51 }
52 int sb=haha();
53 int main(){;}

bzoj3173

时间: 2024-10-09 22:50:03

bzoj3173 最长上升子序列 树状数组的相关文章

hdu 5773 The All-purpose Zero 最长上升子序列+树状数组

题目链接:hdu 5773 The All-purpose Zero 官方题解:0可以转化成任意整数,包括负数,显然求LIS时尽量把0都放进去必定是正确的. 因此我们可以把0拿出来,对剩下的做O(nlogn)的LIS,统计结果的时候再算上0的数量. 为了保证严格递增,我们可以将每个权值S[i]减去i前面0的个数,再做LIS,就能保证结果是严格递增的. 个人看法:对于显然把所以0放进去部分我解释一下: 如果0位于最长上升子序列两边,这两个零要加进去是显然的 如果有一个0夹于最长上升子序列之间,那么

bzoj 2124 等差子序列 树状数组维护hash+回文串

等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 1919  Solved: 713[Submit][Status][Discuss] Description 给一个1到N的排列{Ai},询问是否存在1<=p1<p2<p3<p4<p5<…<pLen<=N (Len>=3), 使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数. 下接T组数据,

CF452F Permutations/Luogu2757 等差子序列 树状数组、Hash

传送门--Luogu 传送门--Codeforces 这种题目还能跟哈希扯上关系也是很神了-- 如果存在长度\(>3\)的等差子序列,那么一定存在长度\(=3\)的等差子序列,所以我们只需要找长度为\(3\)的等差子序列.可以枚举等差子序列的第二个元素\(b\),那么存在长度为\(3\)的等差子序列等价于:可以在\(b\)左边找到一个元素\(a\),在\(b\)右边找到一个元素\(c\),满足\(b - a = c - b\). 对于找到\(ac\)两个元素,一个比较直观的想法是:对\(b\)左

树状数组优化最长上升子序列

最长上升子序列比较暴力的写法是n2 的,实际上我们求得就是前面的比当前小的最长上升子序列的最大值: 树状数组可以优化它: 倒过来求就是最长下降子序列: #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=1e5+10; typedef double dd; typedef long long ll; ll n; ll a[maxn]; ll

[bzoj2124]等差子序列(hash+树状数组)

我又来更博啦 2124: 等差子序列 Time Limit: 3 Sec  Memory Limit: 259 MBSubmit: 941  Solved: 348[Submit][Status][Discuss] Description 给一个1到N的排列{Ai},询问是否存在1<=p1=3),使得Ap1,Ap2,Ap3,…ApLen是一个等差序列. Input 输入的第一行包含一个整数T,表示组数.下接T组数据,每组第一行一个整数N,每组第二行为一个1到N的排列,数字两两之间用空格隔开. O

[CTSC2017]最长上升自序列(伪题解)(树状数组+DP套DP+最小费用最大流+Johnson最短路+Yang_Tableau)

部分分做法很多,但每想出来一个也就多5-10分.正解还不会,下面是各种部分分做法: Subtask 1:k=1 LCS长度最长为1,也就是说不存在j>i和a[j]>a[i]同时成立.显然就是一个LDS,树状数组直接求即可. Subtask 2:k=2 最多两个,也就是可以由两个LCS拼起来,f[i][j]表示第一个LCS以i结尾,第二个以j结尾的方案数,转移显然. Subtask 3:k=2 树状数组优化DP,复杂度由$O(n^3)$降为$O(n^2 \log n)$ Subtask 4,5:

【BZOJ2870】最长道路tree 点分治+树状数组

[BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来往,所以每个路口i都有一个拥挤程度v[i],我们认为从路口s走到路口t的痛苦程度为s到t的路径上拥挤程度的最小值,乘上这条路径上的路口个数所得的积.现在请你求出痛苦程度最大的一条路径,你只需输出这个痛苦程度. 简化版描述: 给定一棵N个点的树,求树上一条链使得链的长度乘链上所有点中的最小权值所得的积

hdu1081 DP类最长子段和(二维压缩+前缀和数组/树状数组计数)

题意:给出一个 n * n 的数字矩阵,问最大子矩阵和是多少. 由于和最长子段和问题类似,一开始想到的就是 DP ,一开始我准备用两个循环进行 DP ,对于每一个 (i,j) ,考察(i - 1,j)与(i,j - 1), dp 值代表以该点为右下角的最大矩阵和,同时记录下这个矩阵的左上角坐标,状态转移时通过将原和最大矩阵通过补边推到当前和最大矩阵.但是其实这种做法有一个明显的问题,就是转移时,补上边后 dp 值相同怎么办,dp 值相同而矩阵不同的话会影响到下一次状态转移后补上的矩阵的情况,从而

HDU - 2227 Find the nondecreasing subsequences (树状数组 + 子序列 + 离散化)

HDU - 2227 Find the nondecreasing subsequences Time Limit: 5000MS   Memory Limit: 32768KB   64bit IO Format: %I64d & %I64u Submit Status Description How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., sn} ? For exa