上个帖子忘加代码了,wssb
几个月没学 oi 打个同学组的复健赛
然而这个题一晚上 + 2h 还调不对
思路是直接莽离散化线段树,把涉及到的所有等级都给离散化
每个线段树的叶子节点维护从 [它的真实等级,下一个离散化的真实等级] 这段区间
然而全 WA 了。。
Wrong Answer.wrong answer The answer is wrong: expected = 7082236.410900, found = 7099498.927800
求浇浇/kk
(LZ在线时间不很连续可能不能及时回复)
#include <iostream>
#include <algorithm>
#define char_phi int
#define re register int
#define FBI_OPENTHEDOOR(x, y) freopen(#x ".in", "r", stdin), freopen(#y ".out", "w", stdout)
#define Diluc 0
#define Endl cout << '\n'
#define _ ' '
#define Dl cerr << '\n'
#define DMARK cerr << "###"
#define N 100005
using namespace std;
inline void Fastio_setup() { ios :: sync_with_stdio(false); cin.tie(NULL), cout.tie(NULL); }
template<typename T> inline T MAX(T A, T B) { return ((A > B) ? (A) : (B)); }
template<typename T> inline T MIN(T A, T B) { return ((A < B) ? (A) : (B)); }
template<typename T> inline T ABS(T A) { return ((A < 0) ? (-A) : (A)); }
/*
这什么,O(nlogn)?
这不对吧
为啥我一眼切
难道是一个前缀和+处理一下期望相同的就ok了?
如果是更改,把更改点以上的同期望改为当前点的同期望
如果是询问,直接再来一个树状数组统计答案就行了,再乘上概率 1 / (r - l + 1)
真切了?
假的
等级的范围
zixiangming句
把所有会出现的等级存起来一起离散化
然而
噢
好像,似乎
用线段树比较好搞
直接对所有等级建线段树
包括询问和修改的等级
都给他搞上
然后如果不是相邻的等级
中间的把贡献算一下扔到靠左的那一个里面
然后直接求和
更新的话
直接把包括这个点到n都给打上lazy
注意记录嗯,每个线段树节点都记录最右边和最左边的真实等级
然后打lazy的时候直接打lazy,查询直接查sum + (ter - tel + 1) * lazy
记录等级直接用set,好查,避免节点重复直接set
直接sort + unique不比这快
试一嘴样例
勾八
不搞了
造个样例搞搞
*/
/*
4 4
1 2
4 3
5 4
7 5
1 1 4
1 4 8
2 6 2
1 4 8
ans
2.7500
10.2000
11.4000
2 1
4 3
2 2
1 1 4
ans
2.2500
2 2
1 3
5 2
1 3 3
1 3 5
ans
3.0000
3.6667
*/
int n, Q;
long long maxlev;
long long Lev[N<<2];
struct Book { long long lev, val; friend bool operator < (Book A, Book B) { return A.lev < B.lev; } };
struct Book bk[N];
struct Question { long long opt, x, y; };
struct Question qus[N];
struct BitTree {
long long C[N<<2];
#define lowbit(x) ((x) & (-(x)))
inline void Update(int k, long long w) { while (k <= Lev[0]) C[k] += w, k += lowbit(k); }
inline long long Query(int k) { long long res = 0; while (k > 0) res += C[k], k -= lowbit(k); return res; }
};
struct BitTree Bit;
struct Segment_Tree {
struct node { long long sum, lz, l, r; };
struct node tr[N<<4];
#define lson (rt << 1)
#define rson (rt << 1 | 1)
#define mid ((l + r) >> 1)
inline void Pushup(int rt) { tr[rt].sum = tr[lson].sum + tr[rson].sum; }
inline void Pushdown(int rt) {
tr[lson].lz += tr[rt].lz, tr[rson].lz += tr[rt].lz;
tr[lson].sum += tr[rt].lz * (tr[lson].r - tr[lson].l + 1);
tr[rson].sum += tr[rt].lz * (tr[rson].r - tr[rson].l + 1);
tr[rt].lz = 0;
}
void Build(int rt, int l, int r) {
if (l == r) {
// tr[rt].sum = Bit.Query(Lev[l]) * (Lev[l+1] - Lev[l]);
tr[rt].l = Lev[l]; tr[rt].r = ((l == Lev[0]) ? (maxlev) : (Lev[l+1]-1));
tr[rt].sum = Bit.Query(l) * (tr[rt].r - tr[rt].l + 1);
// cerr << l << _ << tr[rt].l << _ << tr[rt].r << _ << tr[rt].sum << '\n';
return ;
}
Build(lson, l, mid); Build(rson, mid+1, r);
Pushup(rt);
tr[rt].l = tr[lson].l, tr[rt].r = tr[rson].r;
}
void Update(int rt, int l, int r, int L, int R, long long val) {
if (L <= l and r <= R)
{ tr[rt].lz += val; tr[rt].sum += (tr[rt].r - tr[rt].l + 1) * val; return ; }
if (tr[rt].lz != 0)
Pushdown(rt);
if (L <= mid)
Update(lson, l, mid, L, R, val);
if (R > mid)
Update(rson, mid+1, r, L, R, val);
Pushup(rt);
}
long double Query(int rt, int l, int r, int L, int R, char sus) {
if (L <= l and r <= R)
return ((sus == true) ? ((long double)tr[rt].sum / (tr[rt].r - tr[rt].l + 1)) : (tr[rt].sum));
if (tr[rt].lz != 0)
Pushdown(rt);
if (R <= mid)
return Query(lson, l, mid, L, R, sus);
else if (L > mid)
return Query(rson, mid+1, r, L, R, sus);
else
return Query(lson, l, mid, L, R, sus) + Query(rson, mid+1, r, L, R, sus);
}
};
struct Segment_Tree Segtree;
inline void work() {
cin >> n >> Q;
long long lev, val;
for (re i = 1 ; i <= n ; ++ i)
{ cin >> lev >> val; bk[i] = (Book) { lev, val }; Lev[++ Lev[0]] = bk[i].lev; maxlev = MAX(maxlev, bk[i].lev); }
// cerr << maxlev << '\n';
long long opt, x, y;
for (re i = 1 ; i <= Q ; ++ i) {
cin >> opt >> x >> y; qus[i] = (Question) { opt, x, y }; maxlev = MAX(maxlev, x);
if (opt == 1) Lev[++ Lev[0]] = x, Lev[++ Lev[0]] = y, maxlev = MAX(maxlev, y);// 注意,线段树操作的时候,是Lev[0],不是n
else Lev[++ Lev[0]] = x;
}
sort(bk+1, bk+n+1);
sort(Lev+1, Lev+Lev[0]+1); Lev[0] = unique(Lev+1, Lev+Lev[0]+1) - Lev - 1;// Lev[Lev[0]+1] = maxlev + 1;
/*bk[n+1].lev = 1145141145141919810;
for (re i = 1, j = 1 ; i <= n ; ++ i)
while (Lev[j] < bk[i+1].lev and j <= Lev[0])
Val[j] = bk[i].val, j ++;
for (re i = 1 ; i <= Lev[0] ; ++ i)
Bit.Update(i, Val[i]);*/
for (re i = 1 ; i <= n ; ++ i)
Bit.Update(lower_bound(Lev+1, Lev+Lev[0]+1, bk[i].lev) - Lev, bk[i].val);
/*cerr << Lev[0] << '\n';
for (re i = 1 ; i <= Lev[0] ; ++ i)
cerr << Lev[i] << _ << Val[i] << '\n';*/
Segtree.Build(1, 1, Lev[0]);// 细
cout.setf(ios :: fixed); cout.precision(4);
for (re i = 1 ; i <= Q ; ++ i) {
if (qus[i].opt == 1) {// 比较可爱的询问
if (qus[i].x == qus[i].y)
cout << Segtree.Query(1, 1, Lev[0], lower_bound(Lev+1, Lev+Lev[0]+1, qus[i].x) - Lev, lower_bound(Lev+1, Lev+Lev[0]+1, qus[i].y) - Lev, true) << '\n';
else
cout << Segtree.Query(1, 1, Lev[0], lower_bound(Lev+1, Lev+Lev[0]+1, qus[i].x) - Lev, lower_bound(Lev+1, Lev+Lev[0]+1, qus[i].y) - Lev, false) / (long double)(qus[i].y - qus[i].x + 1) << '\n';
}
else
Segtree.Update(1, 1, Lev[0], lower_bound(Lev+1, Lev+Lev[0]+1, qus[i].x) - Lev, Lev[0], qus[i].y);
}
}
#undef int
// #define Genshin_Impact
char_phi main() {
#ifdef Genshin_Impact
FBI_OPENTHEDOOR(a, a);
#endif
Fastio_setup();
work();
return Diluc;
}