洛谷 P3616 富金森林公园 [树状数组]

传送门

维护一个山脉,单点修改,查询有多少山峰高出水面


我是沙茶沙茶题都不会做只想到无修改可以用扫描线

答案就是所有比水面高的-相邻都比水面高的啊

因为没有区间询问写个$BIT$都可以

有区间询问?可以考虑主席树吧

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
const int N=2e5+5,M=6e5+5;
inline int read(){
    char c=getchar();int x=0,f=1;
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9'){x=x*10+c-'0';c=getchar();}
    return x*f;
}
int n,Q,mp[M],m,a[N];
void iniMP(){
    sort(mp+1,mp+1+m);
    int p=0;
    mp[++p]=mp[1];
    for(int i=2;i<=m;i++) if(mp[i]!=mp[i-1]) mp[++p]=mp[i];
    m=p;
}
int Bin(int v){
    int l=1,r=m;
    while(l<=r){
        int mid=(l+r)>>1;
        if(v==mp[mid]) return mid;
        else if(v<mp[mid]) r=mid-1;
        else l=mid+1;
    }
    return 0;
}
struct Quer{
    int op,h,p;
}q[N];
int c1[M],c2[M];
inline void add(int *c,int p,int v){for(;p;p-=(p&-p)) c[p]+=v;}
inline int sum(int *c,int p){
    int re=0;
    for(;p<=m;p+=(p&-p)) re+=c[p];
    return re;
}
int main(){
    freopen("in","r",stdin);
    n=read();Q=read();
    for(int i=1;i<=n;i++) mp[++m]=a[i]=read();
    for(int i=1;i<=Q;i++){
        q[i].op=read();
        if(q[i].op==1) mp[++m]=q[i].h=read();
        else q[i].p=read(),mp[++m]=q[i].h=read();
    }//puts("hi");
    iniMP();
    for(int i=1;i<=n;i++) a[i]=Bin(a[i]),add(c1,a[i],1),add(c2,min(a[i-1],a[i]),1);
    //for(int i=1;i<=n;i++) printf("%d ",a[i]);puts("");
    for(int i=1;i<=Q;i++){
        q[i].h=Bin(q[i].h);
        if(q[i].op==1) printf("%d
",sum(c1,q[i].h)-sum(c2,q[i].h));
        else{
            int id=q[i].p;
            add(c1,a[id],-1);add(c2,min(a[id-1],a[id]),-1);
            if(id!=n) add(c2,min(a[id],a[id+1]),-1);
            a[id]=q[i].h;
            add(c1,a[id],1);add(c2,min(a[id-1],a[id]),1);
            if(id!=n) add(c2,min(a[id],a[id+1]),1);
        }
    }
}
原文地址:https://www.cnblogs.com/candy99/p/6496754.html