洛谷P3616 富金森林公园

来源:互联网 发布:最为突出的大数据环境 编辑:程序博客网 时间:2024/04/25 16:35

链接

  https://www.luogu.org/problem/show?pid=3616

题解

orz模hhf大佬。

露出水面的部分=露出水面的石头个数-自己和前一个都露出水面的个数。

离散,然后把每块石头的高度丢进权值树状数组(+1);每一个和前一个取min,丢进同一个树状数组(-1),一次询问,直接看大于当前数的和是多少就好了。

代码

//树状数组 #include <cstdio>#include <algorithm>#define maxn 1000000#define lowbit(x) (x&-x)using namespace std;int ta[maxn], tmp[maxn], q[maxn][3], N, a[maxn], tot, M;inline int ls(int x){return lower_bound(tmp+1,tmp+tot+1,x)-tmp;}inline void add(int pos, int v){for(;pos<=tot;pos+=lowbit(pos))ta[pos]+=v;}inline int sum(int pos){int ans=0;for(;pos;pos-=lowbit(pos))ans+=ta[pos];return ans;}int main(){int i;scanf("%d%d",&N,&M);for(i=1;i<=N;i++)scanf("%d",a+i),tmp[++tot]=a[i];for(i=1;i<=M;i++){scanf("%d%d",q[i],q[i]+1);if(q[i][0]==2)scanf("%d",q[i]+2),tmp[++tot]=q[i][2];tmp[++tot]=q[i][1];}sort(tmp+1,tmp+tot+1);for(i=1;i<=N;i++)add(a[i]=ls(a[i]),1);for(i=2;i<=N;i++)add(min(a[i],a[i-1]),-1);for(i=1;i<=M;i++){if(q[i][0]==1){printf("%d\n",1-sum(ls(q[i][1])-1));}else{q[i][2]=ls(q[i][2]);add(a[q[i][1]],-1);add(q[i][2],+1);if(q[i][1]!=1)add(min(a[q[i][1]],a[q[i][1]-1]),+1),add(min(q[i][2],a[q[i][1]-1]),-1);if(q[i][1]!=N)add(min(a[q[i][1]],a[q[i][1]+1]),+1),add(min(q[i][2],a[q[i][1]+1]),-1);a[q[i][1]]=q[i][2];}}return 0;}



0 0