HDU 3450 线段树+二分

点击打开链接

题意:给一个数字序列,问你长度大于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 
#include 
#include 
#include 
#include 
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

你可能感兴趣的:(线段树&树状数组,数据结构,二分,线段树)