[WC/CTS2024] 水镜
首先,这个
我们仔细观察这个题目,可以发现,如果
本质上就是要么满足
于是这个问题就越来越像一个
那就显然想到线段树了。
我们对于线段树上节点,维护这个节点对应区间端点
然后,我们考虑叶子节点怎么求解。假设其对应下标为
接着,考虑怎么合并左右儿子。其实很简单,我们先枚举当前节点左右端点的
node merge(node &x, node &y)
{
node res;
res[0][0] = get2(get1(x[0][0], y[0][0]), get1(x[0][1], y[1][0]));
res[0][1] = get2(get1(x[0][0], y[0][1]), get1(x[0][1], y[1][1]));
res[1][0] = get2(get1(x[1][0], y[0][0]), get1(x[1][1], y[1][0]));
res[1][1] = get2(get1(x[1][0], y[0][1]), get1(x[1][1], y[1][1]));
return res;
}
其中
这也是为什么我们取
于是,我们就可以通过此方法建树,并通过查询在
有一个显然的思路是枚举
这个单调性和正确性显然,就不细说,复杂度
我们还是觉得我们边二分一次边查询一下太慢了,所以考虑把这个二分直接搬到线段树上。
首先,我们先把
所以这个时候,首先取区间复杂度
最后注意一个细节,就是这个
写这道题的意义在于,如果我们要求一个区间的值,但是又有一些
代码
#include <bits/stdc++.h>
using namespace std;
#define maxn 500005
#define ll long long
inline char gc()
{
static char buf[100010], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100010, stdin), p1==p2) ? EOF : *p1++;
}
template<typename T> inline void read(T&x)
{
x = 0;
bool f=0;
static char s = gc();
while(s < '0' || s > '9') f |= s=='-', s = gc();
while(s >= '0' && s <= '9') x = (x << 3) + (x << 1) + (s ^ 48), s = gc();
if(f) x = -x;
}
const long long inf = 1e18;
int n;
ll a[maxn];
pair<ll, ll> get1(pair<ll, ll> x, pair<ll, ll> y)//算交集
{
return make_pair(max(x.first, y.first), min(x.second, y.second));
}
pair<ll, ll> get2(pair<ll, ll> x, pair<ll, ll> y)//算并集
{
return make_pair(min(x.first, y.first), max(x.second, y.second));
}
struct node
{
pair<ll, ll> res[2][2];
node operator +(const node &n)const
{
node now;
now.res[0][0] = get2(get1(res[0][0], n.res[0][0]), get1(res[0][1], n.res[1][0]));
now.res[0][1] = get2(get1(res[0][0], n.res[0][1]), get1(res[0][1], n.res[1][1]));
now.res[1][0] = get2(get1(res[1][0], n.res[0][0]), get1(res[1][1], n.res[1][0]));
now.res[1][1] = get2(get1(res[1][0], n.res[0][1]), get1(res[1][1], n.res[1][1]));
return now;
}
}tree[maxn << 2];
void build(int p, int l, int r)
{
if(l == r)
{
ll sum = a[l] + a[l - 1];
tree[p].res[0][1] = make_pair(sum, inf), tree[p].res[1][0] = make_pair(0, sum);
if(a[l] < a[l - 1]) tree[p].res[0][0] = make_pair(inf, 0), tree[p].res[1][1] = make_pair(0, inf);
else if(a[l] == a[l - 1]) tree[p].res[0][0] = tree[p].res[1][1] = make_pair(inf, 0);
else tree[p].res[0][0] = make_pair(0, inf), tree[p].res[1][1] = make_pair(inf, 0);
return;
}
int mid = (l + r) >> 1;
build(p << 1, l, mid), build(p << 1 | 1, mid + 1, r);
tree[p] = tree[p << 1] + tree[p << 1 | 1];
}
vector<int> q;
vector<pair<int, int> > qwq;
void get_query(int p, int l, int r, int L, int R)
{
if(L > r || R < l) return;
if(L >= l && R <= r) return q.push_back(p), qwq.push_back(make_pair(L, R)), void(0);
int mid = (L + R) >> 1;
get_query(p << 1, l, r, L, mid), get_query(p << 1 | 1, l, r, mid + 1, R);
}
int query(int p, int L, int R, node now)
{
if(L == R) return L;
int mid = (L + R) >> 1;
node Now = tree[p << 1 | 1] + now;
if(Now.res[0][0].first >= Now.res[0][0].second && Now.res[0][1].first >= Now.res[0][1].second
&& Now.res[1][0].first >= Now.res[1][0].second && Now.res[1][1].first >= Now.res[1][1].second)
return query(p << 1 | 1, mid + 1, R, now);
else
return query(p << 1, L, mid, Now);
}
int main()
{
read(n);
for (int i = 1; i <= n; ++i) read(a[i]);
build(1, 2, n);
long long sum = 0;
for (int i = 2; i <= n; ++i)
{
q.clear(), qwq.clear();
get_query(1, 2, i, 2, n);
node now;
now.res[0][0] = now.res[0][1] = make_pair(0, inf);
now.res[1][0] = now.res[1][1] = make_pair(0, inf);
int ans = 1;
for (int j = q.size() - 1; j >= 0; --j)
{
// cout << i << " " << qwq[j].first << " " << qwq[j].second << " " << ans << endl;
node Now = now;
now = tree[q[j]] + now;
if(now.res[0][0].first >= now.res[0][0].second && now.res[0][1].first >= now.res[0][1].second
&& now.res[1][0].first >= now.res[1][0].second && now.res[1][1].first >= now.res[1][1].second)
{
ans = query(q[j], qwq[j].first, qwq[j].second, Now);
// cout << i << " " << qwq[j].first << " " << qwq[j].second << " " << ans << endl;
break;
}
}
sum += i - ans;
}
cout << sum << endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】