题目: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<bits/stdc++.h>
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<R) ans=(ans+query(L,R,mid+1,r,rt<<1|1))%mod;
return ans;
}
ll query1(ll pos,ll l,ll r,ll rt)///查询pos位于b数组的哪个位置
{
if(num[rt]>=pos&&num[rt]-vis[r]<pos)///说明第pos小的数是b[r]
return r;
ll mid=(l+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<R) ans=(ans+query2(L,R,mid+1,r,rt<<1|1));
return ans;
}
int main()
{
int n;
scanf("%d",&n);
int k=0;
for(int i=1;i<=n;i++)
{
scanf("%d%lld%lld",&op[i],&a[i].x,&a[i].y);
if(op[i]==1) b[++k]=a[i].y;
}
sort(b+1,b+1+k);///离散化处理
for(int i=1;i<=n;i++){
if(op[i]==1){
ll id=lower_bound(b+1,b+1+k,a[i].y)-b;
update(id,a[i].x,1,k,1);
vis[id]+=a[i].x;
}
else{
ll l=query1(a[i].x,1,k,1);
ll r=query1(a[i].y,1,k,1);
ll ans=0;
if(l==r)
ans=b[l]*(a[i].y-a[i].x+1)%mod;
else{
ll l=query1(a[i].x,1,k,1);
ll r=query1(a[i].y,1,k,1);
ll k1=((query2(1,l,1,k,1)-a[i].x+1+mod)%mod)*b[l]%mod///l剩余的
ll k2=((a[i].y-query2(1,r-1,1,k,1)+mod)%mod)*b[r]%mod;///r剩余的
ll k0=query(l+1,r-1,1,k,1)%mod;///[l+1,r-1]整段区间的
ans=(k0+k1+k2)%mod;
}
printf("%lld\n",ans);
}
}
return 0;
}