题意:
每个数有一个val和weight,如果val < 0 weight 为 0 , val >= 1e4 weight 为5 ,其余为1.让你求一哥序列使得为weight最大并且val是不下降的.
心得:悲惨背锅。。。不知道怎么该LIS的nlogn做法。。
结果看了挺久。。
最后队友想的方法大概是
其实这个题仔细想一下就是把价值为0的去掉,然后把价值为5的分成5个1的放进去,然后求一次LIS,得到的LIS长度就是最大值了.
PS:如果价值不是5而是很大的数这个方法就不可以了.
看了别人的 ,这才知道怎么用LIS的线段树写法,这样的话可以保证在val为很大的数 的时候也可以。。。
参考http://blog.youkuaiyun.com/howardemily/article/details/78078682
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn = 3e5+5;
int a[maxn], v[maxn], val[maxn], Hash[maxn], id[maxn];
int dp[maxn], treeMax[maxn*4], Max;
void update(int root, int l, int r, int pos, int val)
{
if(l == r)
{
treeMax[root] = max(treeMax[root], val);
return ;
}
int mid = (l+r)/2;
if(pos <= mid) update(root*2, l, mid, pos, val);
else update(root*2+1, mid+1, r, pos, val);
treeMax[root] = max(treeMax[root*2], treeMax[root*2+1]);
}
void query(int root, int l, int r, int i, int j)
{
if(i <= l && j >= r)
{
Max = max(treeMax[root], Max);
return ;
}
int mid = (l+r)/2;
if(mid >= i) query(root*2, l, mid, i, j);
if(mid < j) query(root*2+1, mid+1, r, i, j);
}
int main(void)
{
int x, n = 1;
while(~scanf("%d", &a[n]))
{
v[n] = a[n];
if(a[n] >= 10000) v[n] -= 10000;
if(a[n] >= 10000) val[n] = 5;
else if(a[n] >= 0) val[n] = 1;
else val[n] = 0;
Hash[n] = v[n];
n++;
}
n--;
sort(Hash+1, Hash+1+n);
int d = unique(Hash+1, Hash+1+n)-Hash-1;
for(int i = 1; i <= n; i++)
id[i] = lower_bound(Hash+1, Hash+1+d, v[i])-Hash;
int ans = 0;
for(int i = 1; i <= n; i++)
{
Max = 0;
query(1, 1, n, 1, id[i]);
dp[i] = Max+val[i];
ans = max(ans, dp[i]);
update(1, 1, n, id[i], dp[i]);
}
printf("%d\n", ans);
return 0;
}