码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 3450 线段树+二分

时间:2016-06-09 12:18:43      阅读:218      评论:0      收藏:0      [点我收藏+]

标签:

点击打开链接

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

思路:看了根本不会,都没想到是线段树的题目,弱哭~~~,看了大牛们的题解,算是知道怎么回事了,对于当前的数A,那么以它为最后一个元素可以组成的情况是A-d到A+d的和,也可以这样想,A-d的已经组成了m种情况,那么在不影响小于d的情况下,可以直接将A放到A-d组成的左右序列中,那么直接加就可以了,而后更新A可以组成的情况,数据太大还需要离散化,然后二分找一下A-d和A+d的位置,数据可能没有这两个位置,那么找到第一个大于等于A-d和第一个小于等于A+d的位置更新就行,且不会影响结果,自己写个数据看看就会懂了    PS:多校的题目好难,想着一天刷一套自己部分的题目,而且太难的直接放弃(毕竟太弱),还是有点难以完成啊

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
const int maxn=100010;
const int mod=9901;
int num[maxn<<2],A[maxn],B[maxn];
int n,m;
int lower_1(int val,int k){
    int le=0,ri=k;
    while(ri-le>1){
        int mid=(le+ri)>>1;
        if(B[mid]<=val) le=mid;
        else ri=mid;
    }
    return le+1;
}
void update(int pos,int add,int le,int ri,int node){
    if(le==ri){
        num[node]+=add;
        num[node]%=mod;
        return ;
    }
    int t=(le+ri)>>1;
    if(pos<=t) update(pos,add,le,t,node<<1);
    else update(pos,add,t+1,ri,node<<1|1);
    num[node]=(num[node<<1]+num[node<<1|1])%mod;
}
int query(int l,int r,int le,int ri,int node){
    if(l<=le&&ri<=r) return num[node];
    int ans=0,t=(le+ri)>>1;
    if(l<=t) ans+=query(l,r,le,t,node<<1);
    if(r>t) ans+=query(l,r,t+1,ri,node<<1|1);
    return ans%mod;
}
int main(){
    while(scanf("%d%d",&n,&m)!=-1){
        int k=1,ans=0;
        memset(num,0,sizeof(num));
        for(int i=0;i<n;i++){
            scanf("%d",&A[i]);
            B[i]=A[i];
        }
        sort(B,B+n);
        for(int i=1;i<n;i++){
            if(B[i]!=B[i-1]) B[k++]=B[i];
        }
        for(int i=0;i<n;i++){
            int le=lower_bound(B,B+k,A[i]-m)-B+1;
            int ri=lower_1(A[i]+m,k);
            int pos=lower_bound(B,B+k,A[i])-B+1;
            int ans1=query(le,ri,1,k,1);
            ans=(ans+ans1)%mod;
            update(pos,ans1+1,1,k,1);
        }
        printf("%d\n",ans);
    }
    return 0;
}

HDU 3450 线段树+二分

标签:

原文地址:http://blog.csdn.net/dan__ge/article/details/51620024

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!