hdu6464 线段树

Posted virtu0s0

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu6464 线段树相关的知识,希望对你有一定的参考价值。

http://acm.hdu.edu.cn/showproblem.php?pid=6464

题意

一个空序列,q次操作,一种是往序列后插入x个y,另一种是查询序列中第x小到第y小的数字之和

题解

  • 线段树维护区间和,区间个数

代码

#include<bits/stdc++.h>
#define ll long long 
using namespace std;
const int MAXN=1e5+5;
const int P=1e9+7;
ll V[MAXN<<2],W[MAXN<<2],b[MAXN],lt[MAXN],x[MAXN],y[MAXN];
int sz=0,Q[MAXN];
int tot=0;

void push_up(int o){
    V[o]=V[o<<1]+V[o<<1|1];V[o]%=P;
    W[o]=W[o<<1]+W[o<<1|1];
}
void ud(int o,int l,int r,int p,ll v){
    if(l==r){W[o]+=v;V[o]+=b[l]%P*v%P;V[o]%=P;return;}
    int mid=(l+r)/2;
    if(p<=mid)ud(o<<1,l,mid,p,v);
    else ud(o<<1|1,mid+1,r,p,v);
    push_up(o);
}
int search(int o,int l,int r,ll k){
    if(l==r){lt[++tot]=k;return l;}
    int mid=(l+r)/2;
    if(k<=W[o<<1])return search(o<<1,l,mid,k);
    else return search(o<<1|1,mid+1,r,k-W[o<<1]);
}
ll qy(int o,int l,int r,int L,int R){
    if(L>R)return 0;
    if(L<=l&&r<=R)return V[o];
    int mid=(l+r)/2;
    ll ans=0;
    if(L<=mid){ans+=qy(o<<1,l,mid,L,R);ans%=P;}
    if(R>mid){ans+=qy(o<<1|1,mid+1,r,L,R);ans%=P;}
    return ans;
}
ll qW(int o,int l,int r,int p){
    if(l==r)return W[o];
    int mid=(l+r)/2;
    if(p<=mid)return qW(o<<1,l,mid,p);
    else return qW(o<<1|1,mid+1,r,p);
}

int q;
int id(ll x){
    return lower_bound(b+1,b+sz+1,x)-b;
}
int main(){
    cin>>q;
    for(int i=0;i<q;i++){
        scanf("%d%lld%lld",&Q[i],&x[i],&y[i]);
        if(Q[i]==1)b[++sz]=y[i];
    }
    sort(b+1,b+sz+1);sz=unique(b+1,b+sz+1)-(b+1);
    //for(int i=1;i<=sz;i++)cout<<b[i]<<" ";
    //cout<<endl;
    for(int i=0;i<q;i++){
        if(Q[i]==1){
            ud(1,1,sz,id(y[i]),x[i]);
        }else{
            tot=0;
            int A=search(1,1,sz,x[i]);
            int B=search(1,1,sz,y[i]);    
            //cout<<A<<" "<<B<<endl;
            ll ans=0;
            if(A==B){ans=(lt[2]-lt[1]+1)*b[A]%P;}
            else{
                ans=qy(1,1,sz,A+1,B-1);
                ans+=(qW(1,1,sz,A)-lt[1]+1)*b[A]%P;ans%=P;
                ans+=lt[2]*b[B]%P;ans%=P;
            }
            printf("%lld\n",ans);
        }
    }
}

以上是关于hdu6464 线段树的主要内容,如果未能解决你的问题,请参考以下文章

HDU6464 (权值线段树)-(查找区间第k1小于第k2小之间的和)

hdu-1540线段树刷题

HDU 5692 线段树

HDU 3016 Man Down(线段树)

线段树(HDU1754)

hdu 6287 口算训练(可持久化线段树+线性筛)