您的位置:首页 > 其它

bzoj 3173: [Tjoi2013]最长上升子序列(离线二分+树状数组)

2017-10-04 15:51 411 查看

3173: [Tjoi2013]最长上升子序列

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 2051  Solved: 1041

[Submit][Status][Discuss]

Description

给定一个序列,初始为空。现在我们将1到N的数字插入到序列中,每次将一个数字插入到一个特定的位置。每插入一个数字,我们都想知道此时最长上升子序列长度是多少?

Input

第一行一个整数N,表示我们要将1到N插入序列中,接下是N个数字,第k个数字Xk,表示我们将k插入到位置Xk(0<=Xk<=k-1,1<=k<=N)

Output

N行,第i行表示i插入Xi位置后序列的最长上升子序列的长度是多少。

Sample Input

3

0 0 2

Sample Output

1

1

2

nlogn单调递增:http://blog.csdn.net/jaihk662/article/details/52064213

偷偷建议这题不要看题解!

……

这题的条件其实大大降低了题目难度,首先最后的序列一定是1-n的全排列

其次每次都是加上当前最大的数,这个性质很重要

这就意味着你只要得出最终的序列,然后套一下nlogn的单调递增就可以求出所有答案

令best[x]表示以数字x结尾的最长序列,ans[x]就是第x个答案

那么ans[x]=max(best[i]  (1<=i<=x) )

主要是如何求出最终的序列

倒过来处理,很明显最后一个数所添加的位置一定是最终的位置,然后看下面的例子

假设样例为:

5

0 0 2 1 1

初始序列:

0 0 0 0 0(这一行就是最终序列,为0表示上面没有数字)

0 1 2 3 4(这一行表示前面有多少空位)

5加入第一个数字后面:

0 5 0 0 0

0 0 1 2 3

4加入第一个数字后面:

0 5 4 0 0

0 0 0 1
2

3加入第二个数字后面:

0 5 4 0
3

0 0 0 1 1

2加入最前面:

2 5 4 0 3

x x x 0 0(x的位置已经不可能再放数字了,可以理解为-1)

最后:

2 5 4 1 3(ok)

很显然的:树状数组维护前缀和,然后每次二分求第k个前缀最小

搞定

#include<stdio.h>
#include<algorithm>
using namespace std;
int n, len, cha[100005], tre[100005], a[100005], best[100005], ans[100005];
void Update(int x, int val)
{
while(x<=n)
{
tre[x] += val;
x += x&-x;
}
}
int Query(int x)
{
int sum = 0;
while(x)
{
sum += tre[x];
x -= x&-x;
}
return sum;
}
int Bsech(int x)
{
int l, r, m;
l = 0, r = len;
while(l<r)
{
m = l+(r-l)/2;
if(best[m]>=x)
r = m;
else
l = m+1;
}
return l;
}
int main(void)
{
int i, l, r, m, pos, now;
scanf("%d", &n);
for(i=1;i<=n;i++)
{
scanf("%d", &cha[i]);
Update(i, 1);
}
for(i=n;i>=1;i--)
{
l = 1, r = n;
cha[i] += 1;
while(l<r)
{
m = (l+r)/2;
if(Query(m)<cha[i])
l = m+1;
else
r = m;
}
a[r] = i;
Update(r, -1);
}
len = 1;
best[1] = a[1], ans[a[1]] = 1;
for(i=2;i<=n;i++)
{
if(a[i]>best[len])
best[++len] = a[i], ans[a[i]] = len;
else
{
pos = Bsech(a[i]);
ans[a[i]] = pos;
best[pos] = a[i];
}
}
now = 0;
for(i=1;i<=n;i++)
{
now = max(now, ans[i]);
printf("%d\n", now);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: