首页 > 其他分享 >P3616 富金森林公园 题解

P3616 富金森林公园 题解

时间:2023-09-11 20:33:25浏览次数:46  
标签:ch 富金 int 题解 ans P3616

P3616 富金森林公园 题解

题意

给你 \(n\) 个点,有 \(m\) 次操作,每次操作可以改变一个数的值,也可以查询有多少连续的块,满足这个块内的所有数的值都大于查询的值。

分析

还是比较容易想到用数据结构或分块的,毕竟有同时存在修改和查询操作。但是维护什么?怎么维护?

既然我们无法直接维护答案,那我们去考虑答案有什么性质,能不能通过维护好几个东西给他 乱搞 出来。然后 看完题解后 就会了。

题解

分析一下性质。

先将相邻两个点间的边权赋值为这两个点的较小值,并设当前要查询的值(题里的海拔高度)为 \(x\)。通过手玩样例,我们发现,对于每一个块,块中点权小于 \(x\) 的点数 \(-\) 块中边权小于 \(x\) 的边数 \(= 1\)。那么我们就可以通过维护整个数列中的点权,以及整个数列中的边权来迅速求得块数。即,点权小于 \(x\) 的点数 \(-\) 块中边权小于 \(x\) 的边数 \(=\) 块数。那么就好说了,什么树状数组、线段树随便上就好了。

这里我选择的是常数小还好打的树状数组。

代码

//P3616 富金森林公园
#include <bits/stdc++.h>
#define M 200005

using namespace std;

inline int read() {
    int x = 0, s = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9') {
        if(ch == '-')
            s = -s;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9') {
        x = (x << 3) + (x << 1) + ch - '0';
        ch = getchar();
    }
    return x * s;
}

void write(int x) {
    if(x < 0)  {
        x = ~(x - 1);
        putchar('-');
    }
    if(x > 9)
        write(x / 10);
    putchar(x % 10 + 48);
}

int n, m, a[M], w[M << 1], len, tree1[M << 1], tree2[M << 1];

struct Q {
    int opt;
    int b;
    int c;
    int d;
}q[M];

inline int lowbit(int x) {return x & (-x);}

inline void add(int pos, int addend) {
    for(int i = pos; i <= len; i += lowbit(i))
        tree1[i] += addend;
}

inline void add_edge(int pos, int addend) {
    for(int i = pos; i <= len; i += lowbit(i))
        tree2[i] += addend;
}

inline int ask (int pos) {
    int ans = 0;
    for(int i = pos; i > 0; i -= lowbit(i))
        ans += tree1[i];
    return ans;
}

inline int ask_edge (int pos) {
    int ans = 0;
    for(int i = pos; i > 0; i -= lowbit(i))
        ans += tree2[i];
    return ans;
}

signed main() {
    n = read();
    m = read();
    len = n + m;
    for(int i = 1; i <= n; ++ i)
        w[i] = a[i] = read();
    for(int i = 1; i <= m; ++ i) {
        q[i].opt = read();
        if(q[i].opt == 1) {
            q[i].b = read();
            w[n + i] = q[i].b;
        }
        else {
            q[i].c = read();
            q[i].d = read();
            w[n + i] = q[i].d;
        }
    }
    stable_sort(w + 1, w + len + 1);
    int l = unique(w + 1, w + 1 + len) - w - 1;
    for(int i = 1; i <= n ; ++ i )  {
        a[i] = lower_bound(w + 1, w + 1 + l, a[i]) - w;
        add(a[i], 1);
        if(i > 1)
            add_edge(min(a[i], a[i - 1]), 1);
    }
    for(int i = 1; i <= m; ++ i) {
        if(q[i].opt == 1) {
            q[i].b = lower_bound (w + 1, w + 1 + l, q[i].b) - w;
            write(ask_edge(q[i].b - 1) - ask(q[i].b - 1) + 1);
            putchar('\n');
        }
        else {
            int pos = q[i].c;
            q[i].d = lower_bound(w + 1, w + 1 + l, q[i].d) - w;
            add(q[i].d, 1);
            add(a[pos], -1);
            if(pos != 1) {
                add_edge(min(q[i].d, a[pos - 1]), 1);
                add_edge(min(a[pos], a[pos - 1]), -1);
            }
            if(pos != n) {
                add_edge(min(q[i].d, a[pos + 1]), 1);
                add_edge(min(a[pos], a[pos + 1]), -1);
            }
            a[pos] = q[i].d;
        }
    }
}

后记

放在最后的双倍经验

那道题的题解里有讲的不错的分块做法,可以借鉴一下。

标签:ch,富金,int,题解,ans,P3616
From: https://www.cnblogs.com/Meteor-streaking/p/17691467.html

相关文章

  • 关于sql server 2008 r2 安装闪退问题解决办法
    打开sqlserverr2安装包文件目录找到SQL2008R2_64\2052_chs_lp\x64\setup\sqlsupport_msi目录下sqlsupport.msi,运行安装 a、在安装盘中搜索sqlsupport,找到对应的sqlsupport.msi文件并安装,一般路径如下:Windows64位系统需要安装:..\sql2008r2.iso\2052_chs_lp\x64\setup\sqls......
  • 【ABC105D】题解
    题解题意简述给定\(n\)个数,求这\(n\)个数中有多少个二元组\((x,y)\)满足其中每一个数都是\(m\)的倍数。思路前缀和,\((x,y)\)内每一个数\(\bmod\m=0\),可以用\((sum_y-sum_{x-1})\bmod\m=0\)表示。但是这题数据太大,所以要使用map。如果\(x=1\),......
  • ABC319 A-E 题解
    A用map<string,int>将名字对应的值存下来即可。赛时代码B按照题意暴力模拟,注意细节。赛时代码C答辩题,卡了我半个小时。枚举\(1\sim9\)的全排列,然后按照顺序计算即可,但代码实现比较答辩。赛时代码D显然具有可二分性,直接二分并判定可行性即可,注意不合法条件。赛......
  • 题解 Gym 104531D【Coffee】
    2022SYSUSchoolContest题目不想翻译了,自己看能看懂。problamThegirlsofHTTlikedrinkingtea.Butoneday,theywantedachangeanddecidedtotrycoffeeinthenext\(n\)days.NowMugi,whoalwaysprovidesfoodanddrinksforHTT,willgototheshopto......
  • pycharm 远程debug卡住问题解决
     解决方案:1、先注释掉连接debugserversocket代码,启动 2、启动debugserver3、去除注释,热部署自动重启,则能重连 ......
  • 230909 NOIP 模拟赛 T1 cake 题解
    原题题意有一块\(n\timesm\)\((1\len,m\le14)\)的蛋糕,每个位置上有一个权值\(a_{i,j}\)\((1\lea_{i,j}\le1000)\),现在你要把它切开。每次你可以平行与某一边界把蛋糕切开,所以共有\(n-1\)个可以竖着切的位置,以及\(m-1\)个可以横着切的位置。对于每一组\(i,j\)\(......
  • 【题解】Educational Codeforces Round 142(CF1792)
    没有手速,再加上被E卡了,废掉了。A.GamingForces题目描述:Monocarp正在玩电脑游戏。他打算杀死\(n\)个怪兽,第\(i\)个的血量为\(h_i\)。Monocarp的角色有两个魔法咒语如下,都可以以任意顺序用任意次(可以不用),每次使用相当于一次操作。选择两个怪兽并各扣一滴血。选择......
  • win更新后出现强制同意跨境传输数据问题解决方案
    总体来说就是删除那个更新-  KB5028166解决方法如下:一、在同意个人数据跨境传输界面按ctrl+alt+,进入任务管理器二、按住shift键, 点击右下角关机按钮选择重启三、在弹出的界面选择疑难解答,高级选项四、卸载更新-卸载最新质量更新,卸载完成,重启电脑决这个问题......
  • 题解 LOJ6738【王的象棋世界】
    problem一个\(R\timesC\)的棋盘,你有\(Q\)组询问,每次询问国王走\(R-1\)步从\((1,a)\)到达\((R,b)\)有多少种方案。你只需要输出答案对\(998244353\)取模的结果。\(2\leC\le10^5,C\leR\le10^9,1\leQ\le10^5\)。solution首先DP和矩阵优化DP都比较简单,但......
  • CSP-S2022初赛易错题解析
    一.2.错误原因:不会解析:real代表实际运行时间,user代表用户态运行时间,sys表示内核态运行时间,故选A 5.错误原因:不会解析:基数排序的思路类似于桶排序,故选A 9.错误原因:不会解析:这个问题可以转化成圆排列问题,公式为A(n-1,n-1),即(n-1)!,要考虑从两个方向看的图,所以要除......