CF1609F Interesting Sections
枚举最大值和最小值的 popcount
,扫描线枚举右端点 ,记 表示 中最大值是否等于枚举的 popcount
中最小值是否为枚举的 popcount
,单调栈维护 的变化,那么答案即为 的 的个数,线段树维护即可。时间复杂度均摊 。
#include <bits/stdc++.h>
using namespace std;
namespace Fread
{
const int SIZE = 1 << 23;
char buf[SIZE], *S, *T;
inline char getchar()
{
if (S == T)
{
T = (S = buf) + fread(buf, 1, SIZE, stdin);
if (S == T)
return '\n';
}
return *S++;
}
}
namespace Fwrite
{
const int SIZE = 1 << 23;
char buf[SIZE], *S = buf, *T = buf + SIZE;
inline void flush()
{
fwrite(buf, 1, S - buf, stdout);
S = buf;
}
inline void putchar(char c)
{
*S++ = c;
if (S == T)
flush();
}
struct NTR
{
~NTR()
{
flush();
}
} ztr;
}
#ifdef ONLINE_JUDGE
#define getchar Fread::getchar
#define putchar Fwrite::putchar
#endif
typedef long long ll;
inline ll read()
{
ll x = 0, f = 1;
char c = getchar();
while (c < '0' || c > '9')
{
if (c == '-')
f = -1;
c = getchar();
}
while (c >= '0' && c <= '9')
x = x * 10ll + c - '0', c = getchar();
return x * f;
}
const int _ = 1e6 + 5, M = 62;
int n, t1 = 1, t2 = 1, stk1[_], stk2[_], c[_], cnt[M + 5];
struct abc
{
int p, l, r, v;
};
vector<abc> k[_ + 5];
ll a[_], ans;
struct node
{
int l, r, mx, mxc, lz;
} t[_ << 2];
void pushup(int o)
{
t[o].mx = max(t[o << 1].mx, t[o << 1 | 1].mx);
t[o].mxc = 0;
if(t[o].mx == t[o << 1].mx) t[o].mxc += t[o << 1].mxc;
if(t[o].mx == t[o << 1 | 1].mx) t[o].mxc += t[o << 1 | 1].mxc;
}
void build(int o, int l, int r)
{
t[o].l = l, t[o].r = r, t[o].mx = t[o].lz = 0, t[o].mxc = r - l + 1;
if(l == r) return;
int mid = (l + r) >> 1;
build(o << 1, l, mid), build(o << 1 | 1, mid + 1, r);
}
void tag(int o, int v)
{
t[o].mx += v, t[o].lz += v;
}
void pushdown(int o)
{
if(t[o].lz)
{
tag(o << 1, t[o].lz), tag(o << 1 | 1, t[o].lz), t[o].lz = 0;
}
}
void update(int o, int l, int r, int v)
{
if(l <= t[o].l && t[o].r <= r) return tag(o, v), void();
pushdown(o);
int mid = (t[o].l + t[o].r) >> 1;
// if(r <= mid) update(o << 1, l, r, v);
// else if(l > mid) update(o << 1 | 1, l, r, v);
// else update(o << 1, l, mid, v), update(o << 1 | 1, mid + 1, r, v);
if(l <= mid) update(o << 1, l, r, v);
if(r > mid) update(o << 1 | 1, l, r, v);
pushup(o);
}
signed main()
{
n = read();
for(int i = 1; i <= n; ++i)
{
a[i] = read(), c[i] = __builtin_popcountll(a[i]);
cnt[c[i]]++;
}
for(int i = 1, p; i <= n; ++i)
{
while(t1 > 1 && a[stk1[t1]] > a[i])
{
p = stk1[t1--];
k[c[p]].push_back({i, stk1[t1] + 1, p, -1});
}
k[c[i]].push_back({i, stk1[t1] + 1, i, 1});
while(t2 > 1 && a[stk2[t2]] <= a[i])
{
p = stk2[t2--];
k[c[p]].push_back({i, stk2[t2] + 1, p, -1});
}
k[c[i]].push_back({i, stk2[t2] + 1, i, 1});
stk1[++t1] = i, stk2[++t2] = i;
}
for(int i = 0; i <= M; ++i)
{
if(!cnt[i]) continue;
build(1, 1, n);
for(int j = 1, cur = 0; j <= n; ++j)
{
while(cur < k[i].size() && k[i][cur].p <= j)
{
update(1, k[i][cur].l, k[i][cur].r, k[i][cur].v);
cur++;
}
if(t[1].mx == 2) ans += t[1].mxc;
}
}
printf("%lld\n", ans);
return 0;
}
本文来自博客园,作者:蒟蒻orz,转载请注明原文链接:https://www.cnblogs.com/orzz/p/18121943