P3616 富金森林公园 题解

连通块数 = 点数 边数。

水面海拔为 x 时,点集为海拔 x 的点,所以点数为 i=1n[aix]

两点之间有边,当且仅当两点相邻且两点海拔均 x,所以边数为 i=1n1[min(ai,ai+1)x]

每次单点修改只会影响一个 ai 和两个 min(ai,ai+1),平衡树维护 aimin(ai,ai+1) 的集合即可。

#include <cstdio>
#include <utility>
#include <algorithm>
#include <ext/pb_ds/tree_policy.hpp>
#include <ext/pb_ds/assoc_container.hpp>
#define P pair<int, int>
using namespace std;
using namespace __gnu_pbds;
int n, m, a[300050];
struct S
{
    int c;
    tree<P, null_type, less<P>, rb_tree_tag, tree_order_statistics_node_update> T;
    void I(int x) { T.insert({x, ++c}); }
    void D(int x) { T.erase(T.lower_bound({x, 0})); }
    int Q(int x) { return T.order_of_key({x, 0}); }
} c, d;
int main()
{
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= n; ++i)
        scanf("%d", a + i), d.I(a[i]);
    for (int i = 2; i <= n; ++i)
        c.I(min(a[i], a[i - 1]));
    for (int i = 0, o, x, y; i < m; ++i)
    {
        scanf("%d%d", &o, &x);
        if (o & 1)
            printf("%d\n", c.Q(x) - d.Q(x) + 1);
        else
        {
            scanf("%d", &y);
            d.D(a[x]);
            if (x > 1)
                c.D(min(a[x], a[x - 1]));
            if (x < n)
                c.D(min(a[x], a[x + 1]));
            d.I(a[x] = y);
            if (x > 1)
                c.I(min(a[x], a[x - 1]));
            if (x < n)
                c.I(min(a[x], a[x + 1]));
        }
    }
    return 0;
}
posted @   Jijidawang  阅读(4)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示