题解:P12646 [KOI 2024 Round 1] 升序
Claire0918 · · 题解
我们发现左端点一旦变化每个点的修改次数就会完全不同,于是我们考虑枚举左端点,倒着加入每个数同时维护每个点的操作次数,将询问挂在左端点上做区间查询。
我们注意到如果
Code:
#include<bits/stdc++.h>
#define mem(a, v) memset(a, v, sizeof(a))
using namespace std;
namespace IO{
#define SIZ (1 << 18)
char ibuf[SIZ], *p1 = nullptr, *p2 = nullptr;
#define gc() (p1 == p2 && (p2 = (p1 = ibuf) + fread(ibuf, 1, SIZ, stdin), p1 == p2) ? EOF : *p1++)
template <typename tp>
void rd(tp &x){
x = 0;
int f = 1;
char c = gc();
for (;!isdigit(c); c == '-' && (f = -1), c = gc());
for (;isdigit(c); x = x * 10 + (c ^ 48), c = gc());
x *= f;
}
template <typename tp, typename... Arg>
inline void rd(tp &x, Arg &...args){
rd(x), rd(args...);
}
char obuf[SIZ], *p3 = obuf;
inline void flush(){
fwrite(obuf, 1, p3 - obuf, stdout), p3 = obuf;
}
inline void pc(const char c){
p3 - obuf == SIZ && (flush(), 1538), *p3++ = c;
}
template <typename tp>
void prt(tp x, char ed = '\n'){
x < 0 && (pc('-'), x = -x);
static char stk[40];
int stkp = 0;
do{
stk[stkp] = char(x % 10), x /= 10, ++stkp;
} while (x);
while (stkp){
pc(char(stk[--stkp] + '0'));
}
pc(ed);
}
#undef gc
#undef SIZ
}
using namespace IO;
const int maxn = 250000 + 10, maxq = 250000 + 10;
int n, q;
int a[maxn], tag[maxn];
long long res[maxq];
vector<pair<int, int> > qry[maxn];
stack<int> stk;
namespace segtree{
struct{
int l, r, tag;
long long val;
} tree[maxn << 2];
inline void build(int index, int l, int r){
tree[index].l = l, tree[index].r = r;
if (l == r){
return;
}
const int mid = l + r >> 1;
build(index << 1, l, mid), build(index << 1 | 1, mid + 1, r);
}
inline void _add(int index, long long k){
tree[index].val += (tree[index].r - tree[index].l + 1) * k, tree[index].tag += k;
}
inline void pushdown(int index){
_add(index << 1, tree[index].tag), _add(index << 1 | 1, tree[index].tag), tree[index].tag = 0;
}
inline void add(int index, int l, int r, int k){
if (l <= tree[index].l && r >= tree[index].r){
return _add(index, k);
}
pushdown(index);
const int mid = tree[index].l + tree[index].r >> 1;
l <= mid && (add(index << 1, l, r, k), 1538), r > mid && (add(index << 1 | 1, l, r, k), 1538), tree[index].val = tree[index << 1].val + tree[index << 1 | 1].val;
}
inline long long query(int index, int l, int r){
if (l <= tree[index].l && r >= tree[index].r){
return tree[index].val;
}
pushdown(index);
const int mid = tree[index].l + tree[index].r >> 1;
long long res = 0;
l <= mid && (res += query(index << 1, l, r)), r > mid && (res += query(index << 1 | 1, l, r));
return res;
}
}
using namespace segtree;
int main(){
rd(n, q), build(1, 1, n);
for (int i = 1; i <= n; i++){
rd(a[i]);
}
for (int i = 1; i <= q; i++){
int l, r;
rd(l, r), qry[l].push_back(make_pair(i, r));
}
stk.push(n + 1);
for (int i = n; i; i--){
int l = i + 1, r = stk.top(), posr = i;
while (r <= n){
const long long x = a[l - 1] * (1ll << tag[l - 1]), y = a[l] * (1ll << tag[l]);
if (x > y){
const int k = ceil(log2(double(x) / y));
tag[l] += k, r != l && (tag[r] += k), add(1, l, r, k), stk.pop(), posr = r, l = r + 1, r = stk.top();
}else{
break;
}
}
stk.push(posr);
for (auto x: qry[i]){
res[x.first] = query(1, i, x.second);
}
}
for (int i = 1; i <= q; i++){
prt(res[i]);
}
flush();
return 0;
}