题解 P8618 [蓝桥杯 2014 国 B] Log 大侠
思路
注意到
若
若
由此,我们想到可以使用 map 对其实现删除元素和逐个修改。(都什么年代了还在写传统线段树、传统分块XD)
代码
具体实现上,可以维护整个数组的和,每次修改时减去其差值。
ll n, m, x, Ans;
__gnu_pbds::tree<ll, ll> Mp; // __gnu_pbds::tree 和 map 等效
decltype (Mp.begin ()) it, Lst; // 定义两个 iterator / 迭代器,作用类似于指针
int main ()
{
std::cin.tie (nullptr), std::ios::sync_with_stdio (false);
cin >> n >> m;
For (i, 1, n)
{
cin >> x, Ans += x;
if (x > 2) Mp.insert ({i, x});
}
For (i, 1, m)
{
static ll L, R; cin >> L >> R;
it = Mp.lower_bound (L);
while (it != Mp.end () && it->first <= R)
{
ll Log = log2l (it->second) + 1;
Ans -= it->second - Log;
Lst = it, it = next (it);
if (Log == 2) Mp.erase (Lst);
else Lst->second = Log;
}
cout << Ans << endl;
}
return 0;
}