HDU--2227--Find the nondecreasing subsequences--线段树

Find the nondecreasing subsequences

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 1393    Accepted Submission(s): 494

Problem Description

How many nondecreasing subsequences can you find in the sequence S = {s1, s2, s3, ...., sn} ? For example, we assume that S = {1, 2, 3}, and you can find seven nondecreasing subsequences, {1}, {2}, {3}, {1, 2}, {1, 3}, {2, 3}, {1,
2, 3}.

Input

The input consists of multiple test cases. Each case begins with a line containing a positive integer n that is the length of the sequence S, the next line contains n integers {s1, s2, s3, ...., sn}, 1 <= n <= 100000, 0 <= si <= 2^31.

Output

For each test case, output one line containing the number of nondecreasing subsequences you can find from the sequence S, the answer should % 1000000007.

Sample Input

3
1 2 3

Sample Output

7

题意就是求数列的非递减子序列数量

当你像我一样干了它6个多小时还没AC的时候,心都哇凉了

很容易想到,每输入一个元素,在它之前输入的元素“们”的并且子序列的末尾元素比它小的子序列都可以跟它组成新的子序列

如:1,2,3在输入最后一个3的时候{1},{1,2},{2}都可以跟2组成新序列{1,3}{1,2,3}{2,3},别忘了,3自己还可以弄个新的出来{3}

我看了几乎所有百度得到的博客,不是树桩子就是那种前后比较的压缩型离散线段树,其实,大家都想要一个给力的测试数据,说的没错吧—。—!       那就直接测试50个1,然后100个1,你会发现数字多了之后,小小的差异会变的巨大,就像你们看我博客一次给我一块钱,13亿人都来看...不扯了,嘿嘿

在离散方面出了问题的主要去看看排序是否出错,下面也有点我自己的心得!!

#include <iostream>
#include <cstdio>
#include <algorithm>
#define MM 1000000007
#define Max 100010
using namespace std;
struct node
{
    int l,r,s;	//s:子序列的数量
}tree[Max*6];
struct node1
{
    int a,b;	//a:输入序列的值,b:输入的序列的位置
}sd[Max];
int ss[Max];	//离散化之后的序列
void setit(int l,int r,int d)	//建立,这个不用讲了—。—!
{
    tree[d].l=l;
    tree[d].r=r;
    tree[d].s=0;
    if(l==r)return;
    setit(l,(l+r)/2,d*2);
    setit((l+r)/2+1,r,d*2+1);
}
void insert(int e,int k,int d)	//插入
{
    int l,r,mid;
    l=tree[d].l;
    r=tree[d].r;
    mid=(l+r)/2;
    tree[d].s=(tree[d].s+k)%MM;	//一路遍历下去的同时在这个区间段[l,r]中加k
    if(l==r)return;	//遍历到树叶了就结束
    if(e>mid)insert(e,k,d*2+1);
    else insert(e,k,d*2);
}
int find(int e,int d)
{
    int l,r,mid;
    l=tree[d].l;
    r=tree[d].r;
    mid=(l+r)/2;
    if(e>=r)return tree[d].s;	//如果区间段的右值小于等于e,即确定次区间段类的数字都小于e,就直接返回子序列数
    if(e>mid)return (tree[d*2].s+find(e,d*2+1))%MM;	//e点在区间段的右端时,左子树的子序列数+继续遍历右子树
    else return find(e,d*2);
}
bool cmp(const node1 &a,const node1 &b)
{
    return a.a<b.a||a.a==b.a&&a.b<b.b;	//这里是重点,标记####,下边会讲
}
int main (void)
{
    int n,i,j,k,l,sum;
    while(scanf("%d",&n)!=EOF)
    {
        sum=0;
        setit(0,n,1);
        for(i=0;i<n;i++)
        {
            scanf("%d",&sd[i].a);
            sd[i].b=i;	//标记位置
        }
        sort(sd,sd+n,cmp);	//排序
        for(i=0;i<n;i++)
        ss[sd[i].b]=i;	//把原序列离散成新序列,即把元素弄成1~n,因为元素最大是2^31,数组开不了这么大
        for(i=0;i<n;i++)
        {
            k=(find(ss[i],1)+1)%MM;	//查询可以与当前元素形成新序列的子序列的集合,还有元素自己也可以,所以+1
            sum=(sum+k)%MM;
            insert(ss[i],k,1);	//插入,这里把k插入是因为{1}和{1,3}是不同的,都可以用来和4组成新子序列(假设n=4)
        }
        printf("%d\n",sum);
    }
    return 0;
}

上边的标记

####   sort排序不能很好地处理相同元素的排序,比如我输入50个1,结果后25个1整整齐齐去了前25个1的前面,这样就破坏了原序列的顺序,我这个离散化是1-n的直接标记,比如1,1,7,7会变为1,2,3,4,而还有一种是压缩性的,会变为1,1,2,2,把相同的也保存相同的,这两个有一个会错,原因就是这里讲的sort的缺陷,所以加一个||a.a==b.a&&a.b<b.b意思是在排序的同时,相同元素不会打乱原先的顺序

HDU--2227--Find the nondecreasing subsequences--线段树,布布扣,bubuko.com

时间: 2024-08-12 20:14:17

HDU--2227--Find the nondecreasing subsequences--线段树的相关文章

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

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

HDU 2227 Find the nondecreasing subsequences dp思想 + 树状数组

http://acm.hdu.edu.cn/showproblem.php?pid=2227 用dp[i]表示以第i个数为结尾的nondecreasing串有多少个. 那么对于每个a[i] 要去找 <= a[i]的数字那些位置,加上他们的dp值即可. 可以用树状数组维护 #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algori

HDU 2227 Find the nondecreasing subsequences

树状数组+dp因为今天复习离散化于是手贱加了个离散化 题目大意 意思是给你一段序列,求里面的最长不下降子序列的长度. dp思想 这道题的dp方程非常的好推,看完题目的第一眼就已经推出了方程 设dp[i]表示以当前点为终点的序列方案.所以方程是 \[ dp[i] += (i>j\&\&a[i]\ge a[j])? dp[j]+1:1\ans=\sum_{i=1}^{n}dp[i] \] 但是一看这种方法就是\(n^2\)的复杂度,明显过不了,那怎么办呢? 优化 我们知道,我们最后求得一

hdu 1394 Minimum Inversion Number(线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 10853    Accepted Submission(s): 6676 Problem Description The inversion number of a given number sequence a1, a2, ..., a

HDU 4902 (牛叉的线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

HDU Wow! 4893 Such Sequence!(线段树)

HDU 4893 Wow! Such Sequence! 题目链接 题意:给定一个序列,3种操作,单点添加值,查询区间和,把区间和变成最接近的婓波那契数 思路:线段树,就是第三个操作麻烦,就在结点添加一个值,标记它区间是不是都是婓波那契数了,然后修改区间的时候,如果区间是了就不用修改,如果不是就继续往后一层推即可 代码: #include <cstdio> #include <cstring> #include <cstdlib> #define lson(x) ((x

HDU 4893 Wow! Such Sequence! 水线段树

思路: 线段树走起.. 写完这题就退役T^T 单点更新的时候直接找到这个点的最近fib,然后维护当前和 和 fib的和 #include<stdio.h> #include<string.h> #include<iostream> #include<math.h> #include<algorithm> #include<queue> #include<map> #include<set> #include&l

HDU 1754 I Hate It (线段树 单点更新)

题目链接 中文题意,与上题类似. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 #include <cstdlib> 6 #include <algorithm> 7 const int maxn = 200000+10; 8 using namespace std; 9 int a[maxn], n, m; 10

hdu 4893 Wow! Such Sequence!(线段树功能:单点更新,区间更新相邻较小斐波那契数)

转载请注明出处:http://blog.csdn.net/u012860063?viewmode=contents 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 --------------------------------------------------------------------------------------------------------------------------------------------