zoukankan      html  css  js  c++  java
  • Counting Sequences_线段树***

    Description

    For a set of sequences of integers{a1,a2,a3,...an}, we define a sequence{ai1,ai2,ai3...aik}in which 1<=i1<i2<i3<...<ik<=n, as the sub-sequence of {a1,a2,a3,...an}. It is quite obvious that a sequence with the length n has 2^n sub-sequences. And for a sub-sequence{ai1,ai2,ai3...aik},if it matches the following qualities: k >= 2, and the neighboring 2 elements have the difference not larger than d, it will be defined as a Perfect Sub-sequence. Now given an integer sequence, calculate the number of its perfect sub-sequence. 

    Input

    Multiple test cases The first line will contain 2 integers n, d(2<=n<=100000,1<=d=<=10000000) The second line n integers, representing the suquence

    Output

    The number of Perfect Sub-sequences mod 9901 

    Sample Input

    4 2
    1 3 7 5

    Sample Output

    4

    【题意】给一个数字序列,问长度大于2的且相邻两个数的差的绝对值不大于d的情况对9901取余

    【思路】对于当前的数A,那么以它为最后一个元素可以组成的情况是A-d到A+d的和,也可以这样想,A-d的已经组成了m种情况,那么在不影响小于d的情况下,可以直接将A放到A-d组成的左右序列中,那么直接加就可以了,而后更新A可以组成的情况,数据太大还需要离散化,然后二分找一下A-d和A+d的位置,数据可能没有这两个位置,那么找到第一个大于等于A-d和第一个小于等于A+d的位置更新就行,且不会影响结果。

    参考:http://blog.csdn.net/dan__ge/article/details/51620024

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    const int N=100000+10;
    const int mod=9901;
    int a[N],x[N],sum[4*N];
    int n,m,nn,cnt;
    void build(int k,int l,int r)//建树
    {
        sum[k]=0;
        if(l==r) return ;
        int mid=l+r>>1;
        build(2*k,l,mid);
        build(2*k+1,mid+1,r);
    }
    
    void update(int ll,int rr,int k,int l,int r)
    {
        if(l==r)
        {
            sum[k]=(sum[k]+rr)%mod;
            return ;
        }
        int mid=l+r>>1;
        if(mid>=ll) update(ll,rr,k*2,l,mid);
        if(mid<ll) update(ll,rr,k*2+1,mid+1,r);//
        sum[k]=(sum[k*2]+sum[k*2+1])%mod;
    
    }
    
    int query(int ll,int rr,int k,int l,int r)
    {
        if(ll<=l&&r<=rr) return sum[k]%mod;
        int mid=l+r>>1;
        int res=0;
        if(ll<=mid) res+=query(ll,rr,k*2,l,mid);
        if(mid<rr) res+=query(ll,rr,k*2+1,mid+1,r);
        return res%mod;
    }
    
    int main()
    {
        while(~scanf("%d%d",&n,&m))
        {
            cnt=0;
            for(int i=0;i<n;i++)
            {
                scanf("%d",&a[i]);
                x[cnt++]=a[i];
                x[cnt++]=a[i]-m;
                x[cnt++]=a[i]+m;
            }
            sort(x,x+cnt);
            nn=unique(x,x+cnt)-x;//nn去重后,不重复元素的个数;STLunqiue在STL中unique函数是一个去重函数,unique的功能是去除相邻的重复元素(只保留一个),
    //其实它并不真正把重复的元素删除,是把重复的元素移到后面去了,然后依然保存到了原数组中,然后 返回去重后最后一个元素的地址,
    //因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序。 build(
    1,1,nn); int ans=0; for(int i=0;i<n;i++) { int p=lower_bound(x,x+nn,a[i])-x;//Lower_bound是小于等于关键字的位置 int left=lower_bound(x,x+nn,a[i]-m)-x; int right=lower_bound(x,x+nn,a[i]+m)-x; int c=query(left+1,right+1,1,1,nn); update(p+1,c+1,1,1,nn); ans=(ans+c)%mod; } printf("%d ",ans); } return 0; }
  • 相关阅读:
    【HDOJ】1558 Segment set
    【HDOJ】2395 Alarm Clock
    【HDOJ】4278 Faulty Odomete
    【HDOJ】2571 命运
    【HDOJ】2150 Pipe
    【HDOJ】1277 全文检索
    【HDOJ】1134 Game of Connections
    【HDOJ】5131 Song Jiang's rank list
    【HDOJ】2772 Matchsticks
    【HDOJ】2577 How to Type
  • 原文地址:https://www.cnblogs.com/iwantstrong/p/6057524.html
Copyright © 2011-2022 走看看