线段树+树状数组
线段树维护a序列的最小值(初始值为b,多次查询区间最值,当区间最小值为0时更新树状数组
//982MS 4764K
#include <bits/stdc++.h>
#define mid (l+r)/2
#define lowbit(x) x&-x
using namespace std;
const int MAX=1e5+1;
int a[MAX*4],lazy[MAX*4],b[MAX],c[MAX];
int n,m;
void init()
{
memset(lazy,0,sizeof(lazy));
memset(c,0,sizeof(c));
}
int read(int &x)
{
x=0;int f=1;char s=getchar();
while (s>'9'||s<'0'){if(s=='-')f=-1;s=getchar();}
while (s<='9'&&s>='0'){x=x*10+s-'0';s=getchar();}
return x*=f;
}
void update_(int x)
{
while (x<=n){c[x]++;x+=lowbit(x);}
}
int get_(int x)
{
int sum=0;
while (x){sum+=c[x];x-=lowbit(x);}
return sum;
}
void pushup(int t)
{
a[t]=min(a[t*2],a[t*2+1]);
}
void pushdown(int t)
{
a[t*2]-=lazy[t];
a[t*2+1]-=lazy[t];
lazy[t*2]+=lazy[t];
lazy[t*2+1]+=lazy[t];
lazy[t]=0;
}
void build(int t,int l,int r)
{
if(l==r)
{
a[t]=b[r];
return ;
}
build(t*2,l,mid);
build(t*2+1,mid+1,r);
pushup(t);
}
void updatepos(int t,int l,int r)
{
if(l==r)
{
if(a[t]==0)
{
update_(l);
a[t]=b[l];
}
return ;
}
if(lazy[t]>0) pushdown(t);
if (a[t*2]==0) updatepos(t*2,l,mid);
if (a[t*2+1]==0) updatepos(t*2+1,mid+1,r);
pushup(t);
}
void update(int t,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
a[t]--;
lazy[t]++;
updatepos(t,l,r);
return;
}
if(lazy[t]>0) pushdown(t);
if(mid>=L) update(t*2,l,mid,L,R);
if(mid<R) update(t*2+1,mid+1,r,L,R);
pushup(t);
}
bool query(int t,int l,int r,int L,int R)
{
if(l>=L&&r<=R)
{
if (a[t]==0)
{
updatepos(t,l,r);
return 1;
}
else return 0;
}
int sum=0;
if(mid>=L&&a[t]==0) sum+=query(t*2,l,mid,L,R);
if(mid<R&&a[t]==0) sum+=query(t*2+1,mid+1,r,L,R);
pushup(t);
return sum>0;
}
int main ()
{
int x,y;
char s[5];
while (~scanf("%d%d",&n,&m))
{
init();
for(int k=1;k<=n;k++) read(b[k]);
build(1,1,n);
while (m--)
{
scanf("%s",s);
read(x);read(y);
if(*s=='a')
{
update(1,1,n,x,y);
while(query(1,1,n,x,y)){}
}
else
printf("%d\n",get_(y)-get_(x-1));
}
}
return 0;
}

本文介绍了一种结合线段树与树状数组解决HDU6315问题的方法。通过线段树维护序列的最小值,并利用树状数组进行区间更新,实现了高效的查询与更新操作。

104

被折叠的 条评论
为什么被折叠?



