树状数组 洛谷P3616 富金森林公园
P3616 富金森林公园
题目描述
博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N。每一个巨石有一个海拔高度。而这个山脉又在一个盆地中,盆地里可能会积水,积水也有一个海拔高度,所有严格低于这个海拔高度的巨石,就会在水面下隐藏。
由于地壳运动,巨石的海拔高度可能会随时变化,每次一块的巨石会变成新的海拔高度。当然,水面的高度也会随时发生变化。
因为有这样奇妙的地质奇观,吸引了很多游客来游玩。uim作为一个游客,可以告诉你此时水位海拔,你得告诉他,能看到有几个连续露出水面的部分。(与水面持平我们也认为是露出)
输入输出格式
输入格式:
第一行两个整数N和M,分别表示N块石头,M个询问。
接下来一行,N个整数Ai表示每个巨石的初始海拔。
接下来M行,每行有两个或者三个数,每一行如果第一个数是1,那么后面跟一个Bj,表示水面海拔。如果第一个数是2,后面跟两个整数,Cj和Dj,表示编号Cj的巨石海拔变为Dj。
输出格式:
对于每个"1"询问,给出一个整数答案,也就是露出了几部分的山峰。
好题。不过自己没有想出来。
首先可以知道这是一道数据结构题。那么我们就要确定自己要维护什么东西。
看到询问问的是在给定高度之上的,那么我们就可以用树状数组维护每一个山的高度,即树状数组里存的是在这个高度之上的山的数目。
这样利用差分,我们可以做到区间修改,然后在树状数组内直接单点查询。
又因为我们树状数组的下标是高度,所以需要离散化一下。
因为给出了初始高度,所以我们可以O(n)的扫一遍预处理出树状数组的初值。
对于查询操作,直接O(1)查询即可。
对于修改操作,我们要考虑当前位置与它前一个和后一个的高度的关系,但是分情况讨论太麻烦了,所以我们可以直接判断之前这三个之间高度差,也就是将之前的树状数组里在这个高度的值全部清空,再判断当前重新加值。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int wx=4000017;
int maxn;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int n,m,top;
int sum[wx],h[wx],st[wx],que[wx],opt[wx];
void add(int pos,int k){
for(int i=pos;i<=4000000;i+=(i&-i)){
sum[i]+=k;
}
}
int query(int x){
int re=0;
for(int i=x;i>=1;i-=(i&-i)){
re+=sum[i];
}
return re;
}
struct node{
int pos,v;
}q[wx];
int main(){
n=read();m=read();
for(int i=1;i<=n;i++){
h[i]=read();st[++top]=h[i];maxn=max(maxn,h[i]);
}
for(int i=1;i<=m;i++){
opt[i]=read();
if(opt[i]==1){
que[i]=read();st[++top]=que[i];
}
else{
q[i].pos=read();
q[i].v=read();st[++top]=q[i].v;
}
}
sort(st+1,st+1+top);
for(int i=1;i<=n;i++){
h[i]=lower_bound(st+1,st+1+top,h[i])-1-st;
}
for(int i=1;i<=m;i++){
if(opt[i]==1){
que[i]=lower_bound(st+1,st+1+top,que[i])-st-1;
}
else {
q[i].v=lower_bound(st+1,st+1+top,q[i].v)-st-1;
}
}
for(int i=1;i<n;i++){
if(h[i]>h[i+1]){
add(h[i+1]+1,1);
add(h[i]+1,-1);
}
}
for(int i=1;i<=m;i++){
if(opt[i]==1){
int ans=query(que[i]);
if(h[n]>=que[i])ans++;
printf("%d\n",ans);
}
else{
if(q[i].pos!=1)if(h[q[i].pos-1]>h[q[i].pos])add(h[q[i].pos]+1,-1),add(h[q[i].pos-1]+1,1);
if(q[i].pos!=n)if(h[q[i].pos]>h[q[i].pos+1])add(h[q[i].pos+1]+1,-1),add(h[q[i].pos]+1,1);
h[q[i].pos]=q[i].v;
if(q[i].pos!=1)if(h[q[i].pos-1]>h[q[i].pos])add(h[q[i].pos]+1,1),add(h[q[i].pos-1]+1,-1);
if(q[i].pos!=n)if(h[q[i].pos]>h[q[i].pos+1])add(h[q[i].pos+1]+1,1),add(h[q[i].pos]+1,-1);
// if(h[q[i].pos]<=h[q[i].pos-1]&&h[q[i].pos]+q[i].v<=h[q[i].pos-1])add(h[q[i].pos]+1,1),add(h[q[i].pos]+q[i].v+1,-1);
// if(h[q[i].pos]<=h[q[i].pos-1]&&h[q[i].pos]+q[i].v>h[q[i].pos-1])add(h[q[i].pos],-1),add(h[q[i].pos-1]+1,-1);
// if(h[q[i].pos]<h[q[i].pos+1]&&h[q[i].pos]+q[i].v>=h[q[i].pos+1])add(h[q[i].pos]+1,1),add(h[q[i].pos]+q[i].v+1,-1);
// if(h[q[i].pos]>=h[q[i].pos+1])add(h[q[i].pos]+1,1),add(h[q[i].pos]+q[i].v+1,-1);
// h[q[i].pos]+=q[i].v;
}
}
}
树状数组 洛谷P3616 富金森林公园的更多相关文章
- 洛谷 P3616 富金森林公园题解(树状数组)
P3616 富金森林公园 题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有 ...
- 洛谷P3616 富金森林公园
题目描述 博艾的富金森林公园里有一个长长的富金山脉,山脉是由一块块巨石并列构成的,编号从1到N.每一个巨石有一个海拔高度.而这个山脉又在一个盆地中,盆地里可能会积水,积水也有一个海拔高度,所有严格低于 ...
- ●洛谷 P3616 富金森林公园
题链: https://www.luogu.org/problemnew/show/3616 题解: 树状数组,,, 本题思路挺巧妙. 考虑这种暴力算法:(设H[i]为i位置的高度,水面的高度为B) ...
- 洛谷 P3616 富金森林公园 [树状数组]
传送门 维护一个山脉,单点修改,查询有多少山峰高出水面 我是沙茶沙茶题都不会做只想到无修改可以用扫描线 答案就是所有比水面高的-相邻都比水面高的啊 因为没有区间询问写个$BIT$都可以 有区间询问?可 ...
- P3374 【模板】树状数组 1--洛谷luogu
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某一个数加上x 2.求出某区间每一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- P3368 【模板】树状数组 2--洛谷luogu
题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的值 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...
- 洛谷P2617 Dynamic Ranking(主席树,树套树,树状数组)
洛谷题目传送门 YCB巨佬对此题有详细的讲解.%YCB%请点这里 思路分析 不能套用静态主席树的方法了.因为的\(N\)个线段树相互纠缠,一旦改了一个点,整个主席树统统都要改一遍...... 话说我真 ...
- [洛谷P1198/BZOJ1012][JSOI2008] 最大数 - 树状数组/线段树?
其实已经学了树状数组和线段树,然而懒得做题,所以至今没写多少博客 Description 现在请求你维护一个数列,要求提供以下两种操作: 1. 查询操作. 语法:Q L 功能:查询当前数列中末尾L个数 ...
- 洛谷P3655 差分数组 树状数组
题目链接:https://www.luogu.org/problemnew/show/P3655 不一定对,仅供参考,不喜勿喷,不喜勿喷. 先copy洛谷P3368 [模板]树状数组 2 题解里面一位 ...
随机推荐
- linux命令学习笔记(53):route命令
Linux系统的route命令用于显示和操作IP路由表(show / manipulate the IP routing table).要实现两 个不同的子网之间的通信,需要一台连接两个网络的路由器, ...
- 《Javascript高级程序设计》阅读记录(一):第二、三章
<Javascript高级程序设计>阅读记录(一) 这个系列,我会把阅读<Javascript高级程序设计>之后,感觉讲的比较深入,而且实际使用价值较大的内容记录下来,并且注释 ...
- mac下无法远程桌面连接win10的解决办法
原文链接:http://www.hangge.com/blog/cache/detail_899.html 原来在Mac OSX下远程win7系统很正常,后来把windows系统升级成了win10,再 ...
- VS Code:快捷方式
转于:vscode: Visual Studio Code 常用快捷键 博主:魚魚 更多操作参见官网:https://code.visualstudio.com/docs/getstarted/key ...
- IDEA常用快捷键整理
快速定位文件: Ctrl+E,最近的文件 Ctrl+Shift+E,最近更改的文件 Alt+Shift+C,最近打开的文件 Ctrl+N,快速打开类 Ctrl+Shift+N,快速打开文件 当 ...
- 忘记mysql密码,但是可以用navicat修改MySQL密码
1.首先:要知道你的账户 2.打开可以连接的navicat,在查询语句页面,输入以下操作,就可以修改成功密码了
- <%@ include file=""%>与<jsp:include page=""/>两种方式的作用
一.前言 身为一名coder有太多太多的知识点要去学,太多太多的东西要去记.往往一些小细节也就难免疏忽,但悲催的是多数困恼你的bug就是因为这些微不足道的知识点.我们又不是机器人,怎么可能什么都记得了 ...
- eclipse安装WTP部署WEB项目
打开WTP官方安装指南,找到想要的下载站点 http://wiki.eclipse.org/WTP_FAQ#How_do_I_install_WTP.3F 我选择的是http://download.e ...
- Java探索之旅(6)——对象和类
1.知识要点 假设: public ClassName{ int data; String name; ClassName(){data=1;} public static ...
- xgene:疾病相关基因,耳聋,彩色,老年痴呆,帕金森
神经元的传递:一个下游神经元,它接受其上游神经元的各个突触传过来的信号,然而,每个突触对该下游神经元的激活权重是不同的. 从神经网络的本质上说,当人连续.多次遭受失败的时候,大脑内就会释放大量的抑制性 ...