版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Maxwei_wzj/article/details/83315737
测试地址:富金森林公园
做法: 本题需要用到线段树。
一道好题,不看题解乍一下真的不知道怎么做…
我们考虑直接维护水面在高度
时能看见的连续段数
,考虑一块石头高度的增减对
的影响。为了讨论方便,我们把修改操作都看成是,先把石头高度降到最低,再把石头高度升到新的高度,这样只用考虑两个过程就可以了,并且我们发现这两个过程产生的贡献完全相反,因此我们现在只考虑升的过程就好了。
考虑这块石头相邻的两块石头高度
,假定
,那么在当前石头升到高度
这一段,水面高度在这一段时的答案应该
,因为两块被连接成一块;而在高度从
升到
的这一段,水面高度为这一段时的答案不发生变化,因为原来是一段,现在还是一段;当升到比
高时,水面高度为这一段时的答案会
,因为原来这里没有石头,现在多出来了一块。这样讨论之后,我们发现用线段树进行区间修改就能完成这一题了,时间复杂度为
。
以下是本人代码:
#include <bits/stdc++.h>
using namespace std;
int n,m,tot,a[200010]={0},h[200010],op[200010],opx[200010],opid[200010];
int seg[2000010]={0},tag[2000010]={0};
struct forsort
{
bool type;
int id,val;
}f[400010];
bool cmp(forsort a,forsort b)
{
return a.val<b.val;
}
void pushdown(int no,int l,int r)
{
int mid=(l+r)>>1;
if (tag[no]!=0)
{
tag[no<<1]+=tag[no],tag[no<<1|1]+=tag[no];
seg[no<<1]+=tag[no]*(mid-l+1);
seg[no<<1|1]+=tag[no]*(r-mid);
tag[no]=0;
}
}
void pushup(int no)
{
seg[no]=seg[no<<1]+seg[no<<1|1];
}
void segmodify(int no,int l,int r,int s,int t,int d)
{
if (l>=s&&r<=t)
{
seg[no]+=(r-l+1)*d;
tag[no]+=d;
return;
}
int mid=(l+r)>>1;
pushdown(no,l,r);
if (s<=mid) segmodify(no<<1,l,mid,s,t,d);
if (t>mid) segmodify(no<<1|1,mid+1,r,s,t,d);
pushup(no);
}
int query(int no,int l,int r,int x)
{
if (l==r) return seg[no];
int mid=(l+r)>>1;
pushdown(no,l,r);
if (x<=mid) return query(no<<1,l,mid,x);
else return query(no<<1|1,mid+1,r,x);
}
void modify(int id,int type)
{
if (min(a[id],min(a[id-1],a[id+1]))>0)
segmodify(1,1,tot,1,min(a[id],min(a[id-1],a[id+1])),-type);
if (a[id]>max(a[id-1],a[id+1]))
segmodify(1,1,tot,max(a[id-1],a[id+1])+1,a[id],type);
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&f[i].val);
f[i].type=0,f[i].id=i;
}
for(int i=1;i<=m;i++)
{
scanf("%d",&op[i]);
if (op[i]==1) scanf("%d",&f[n+i].val);
else scanf("%d%d",&opid[i],&f[n+i].val);
f[n+i].type=1,f[n+i].id=i;
}
sort(f+1,f+n+m+1,cmp);
tot=0;
for(int i=1;i<=n+m;i++)
{
if (i==1||f[i].val!=f[i-1].val)
tot++;
if (!f[i].type) h[f[i].id]=tot;
else opx[f[i].id]=tot;
}
for(int i=1;i<=n;i++)
{
a[i]=h[i];
modify(i,1);
}
for(int i=1;i<=m;i++)
{
if (op[i]==1) printf("%d\n",query(1,1,tot,opx[i]));
else
{
modify(opid[i],-1);
a[opid[i]]=opx[i];
modify(opid[i],1);
}
}
return 0;
}