离散化+线段树

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

分析:

每次1操作会往序列底加first个second,first 和 second 都是最大1e9的数据,每次2操作询问序列中第first到第second个数的和

一开始就感觉有点像线段树,输入数据太大我们可以离线处理把数据离散化下,然后扔到线段树上,维护两个数组:

sum: 区间数的值的和  num: 区间数的数量和  ,对于每次询问的first和second,我们找到第first个和第second个分别是哪两个数字,

如果两个数字不相同,那么就先算出分别取了多少个这两个数字,对于两个数字中间的数字和我们可以直接用线段树区间求和得到

Ac code:

#include
using namespace std;
typedef long long ll;
const int maxn=100001;
const ll mod=1e9+7;
struct Node{
    ll x,y;
};
Node a[maxn];
int op[maxn];
ll b[maxn],sum[maxn<<2],num[maxn<<2],vis[maxn];
void update(ll pos,ll val,ll l,ll r,ll rt)
{
    if(l==r){
        sum[rt]=(sum[rt]+(b[pos]*val)%mod)%mod;
        num[rt]+=val;
        return;
    }
    ll mid=(l+r)>>1;
    if(pos<=mid) update(pos,val,l,mid,rt<<1);
    else update(pos,val,mid+1,r,rt<<1|1);
    sum[rt]=(sum[rt<<1]+sum[rt<<1|1])%mod;
    num[rt]=num[rt<<1]+num[rt<<1|1];
}
ll query(ll L,ll R,ll l,ll r,ll rt)///区间查询[L,R]的数的值的和
{
    if(L<=l&&r<=R){
        return sum[rt]%mod;
    }
    ll mid=(l+r)>>1;
    ll ans=0;
    if(L<=mid) ans=(ans+query(L,R,l,mid,rt<<1))%mod;
    if(mid=pos&&num[rt]-vis[r]>1;
    if(pos<=num[rt<<1]) query1(pos,l,mid,rt<<1);
    else  query1(pos-num[rt<<1],mid+1,r,rt<<1|1);
}
ll query2(ll L,ll R,ll l,ll r,ll rt)///求区间[L,R]有多少个数字
{
    if(L<=l&&r<=R)
        return num[rt];
    ll mid=(l+r)>>1;
    ll ans=0;
    if(L<=mid) ans=(ans+query2(L,R,l,mid,rt<<1));
    if(mid

 

你可能感兴趣的:(数据结构)