直接上平衡树乱搞。
也可以离散化后线段树维护子树大小和区间和(平衡树不用离散化)
用的是Treap。
#include <cstdio>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
const ll maxn = 200005;
const ll mod = 1000000007;
ll ch[maxn][2], val[maxn], pri[maxn];
ll tot, rt;
ll siz[maxn], num[maxn], sum[maxn];
#define ls ch[now][0]
#define rs ch[now][1]
inline void pushUp(ll now)
{
siz[now] = siz[ls] + siz[rs] + num[now];
sum[now] = ((sum[ls] + sum[rs]) % mod + (val[now] * num[now]) % mod) % mod;
}
void rotate(ll &x, ll dir)
{
ll son = ch[x][dir];
ch[x][dir] = ch[son][dir ^ 1];
ch[son][dir ^ 1] = x;
pushUp(x);
pushUp(x = son);
}
inline void newNode(ll v, ll cnt, ll &now)
{
now = ++tot;
ls = rs = 0;
num[now] = siz[now] = cnt;
val[now] = v;
pri[now] = rand();
}
void insert(ll v, ll cnt, ll &now)
{
if (!now)
{
newNode(v, cnt, now);
sum[now] = v * cnt % mod;
return;
}
if (val[now] == v)
{
num[now] += cnt;
siz[now] += cnt;
sum[now] = (sum[now] + cnt * v % mod) % mod;
return;
}
if (v < val[now])
{
insert(v, cnt, ls);
if (pri[ls] < pri[now])
rotate(now, 0);
}
else
{
insert(v, cnt, rs);
if (pri[rs] < pri[now])
rotate(now, 1);
}
pushUp(now);
}
ll query(ll k, ll now)
{
if (!k)
return 0;
if (siz[ls] < k && siz[ls] + num[now] >= k)
return (sum[ls] + ((k - siz[ls]) * val[now]) % mod) % mod;
else if (k <= siz[ls])
return query(k, ls) % mod;
else
return ((sum[now] - sum[rs]) % mod + query(k - siz[ls] - num[now], rs)) % mod;
}
ll Q;
int main()
{
scanf("%I64d", &Q);
ll op;
ll a, b;
while (Q--)
{
scanf("%I64d%I64d%I64d", &op, &a, &b);
if (op == 1)
insert(b, a, rt);
else
printf("%I64d\n", ((query(b, rt) - query(a - 1, rt)) % mod + mod) % mod);
}
}