题意
一个长度为 $n$ 的序列,对于每个前缀,求最多 $5$ 个互不相交的不下降子序列的元素和的最大值。
$n\leq 10^5,a_i\in[1,10^9]$
题解
$5$ 这个东西很有用,最终的复杂度很可能就是跟 $2^5$ 之类的相关。
把 $a_i$ 拆成 $a_i$ 个 $a_i$,那么答案转变成统计元素数量的最大值。
发现这个东西就是杨氏图表前 $5$ 层的长度之和。
杨表的插入过程如下:
1,若当前层没有元素比 $x$ 大,则把 $x$ 插在末尾。
2,否则用比 $x$ 大的最小的数 $y$ 代替 $x$,然后将 $y$ 插入下一层中。
那么用 $\mbox{map}$ 处理杨表,每次插入 $a_i$ 个 $a_i$,每层最多会使 $2$ 个数字拆开,因此时间复杂度 $O(2^5n\log n)$。
代码
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 
 | #include <cstdio>#include <iostream>
 #include <map>
 #include <cstring>
 using namespace std;
 #define ll long long
 #define S 5
 inline int read()
 {
 int x=0; char ch=getchar();
 for(;ch<'0'||ch>'9';ch=getchar());
 for(;ch>='0'&&ch<='9';ch=getchar()) x=(x<<3)+(x<<1)+(ch^48);
 return x;
 }
 map<int,ll> a[S];
 ll ans;
 void add(int k,ll num,int u)
 {
 if(k>=S) return;
 a[k][u]+=num; ans+=num;
 for(map<int,ll>::iterator it;num;)
 {
 it=a[k].lower_bound(u+1);
 if(it==a[k].end()) break;
 ll d=min((*it).second,num);
 num-=d; ans-=d;
 add(k+1,d,(*it).first);
 if((*it).second==d) a[k].erase(it); else a[k][(*it).first]-=d;
 }
 }
 int main()
 {
 for(int T=read();T;T--,ans=0)
 {
 for(int i=0;i<S;i++) a[i].clear();
 for(int i=read(),x,n=i;i;i--) x=read(),add(0,x,x),printf((i==1)?"%lld\n":"%lld ",ans);
 }
 return 0;
 }
 
 |