4355: Play with sequence
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 300 Solved: 91
[Submit][Status][Discuss]
Description
维护一个长度为N的序列a,现在有三种操作:
1)给出参数U,V,C,将a[U],a[U+1],...,a[V-1],a[V]都赋值为C。
2)给出参数U,V,C,对于区间[U,V]里的每个数i,将a[i]赋值为max(a[i]+C,0)。
3)给出参数U,V,输出a[U],a[U+1],...,a[V-1],a[V]里值为0的数字个数。
Input
第一行包含两个正整数N,M(1<=N,M<=300000),分别表示序列长度和操作个数。
第二行包含N个整数,其中第i个数表示a[i](0<=a[i]<=10^9),描述序列的初始状态。
接下来M行描述M个操作,保证1<=U<=V<=N,对于操作1,0<=C<=10^9,对于操作2,|C|<=10^9。
Output
输出若干行,每行一个整数,依次回答每个操作3的问题。
Sample Input
5 3
6 4 6 6 4
2 1 5 -5
1 3 4 4
3 1 5
Sample Output
2
HINT
2016.1.1新加数据
Source
推荐一篇博客。
类似题: hdu 5306
代码:
#include<bits/stdc++.h>
#define lson (i<<1)
#define rson (i<<1|1)
using namespace std;
typedef long long ll;
const ll inf =1e17+5;
const int N =3e5+5;
ll a[N];
struct node
{
ll mn,cmn;
ll cnt;
ll lz;
ll cov;
ll add;
int l,r;
}tr[N<<2];
void solve(int i,ll cov)
{
int l,r; l=tr[i].l; r=tr[i].r;
tr[i].mn=cov;
tr[i].cnt=r-l+1;
tr[i].cmn=inf;
tr[i].lz=-inf;
tr[i].add=0;
tr[i].cov=cov;
return ;
}
void solve1(int i,ll add)
{
int l,r; l=tr[i].l; r=tr[i].r;
tr[i].mn+=add;
if(tr[i].cmn!=inf) tr[i].cmn+=add;
if(tr[i].lz!=-inf ) tr[i].lz+=add;
if(tr[i].cov!=inf ) tr[i].cov+=add;
else tr[i].add+=add;
}
void solve2(int i,ll lz)
{
if(lz>tr[i].mn){ //如果当前的lz大于当前的最小值
//那么要更新当前的最小值为lz 因为是push_down
tr[i].lz=lz;
tr[i].mn=lz;
}
}
void push_up(int i)
{
tr[i].mn=min(tr[lson].mn,tr[rson].mn);
if(tr[lson].mn==tr[rson].mn){
tr[i].cnt=tr[lson].cnt+tr[rson].cnt;
tr[i].cmn=min(tr[lson].cmn,tr[rson].cmn);
}
else if(tr[lson].mn<tr[rson].mn){ // 左孩子的最小值小
tr[i].cnt=tr[lson].cnt;
tr[i].cmn=min(tr[lson].cmn,tr[rson].mn);
}
else{ // 右孩子的最小值最小
tr[i].cnt=tr[rson].cnt;
tr[i].cmn=min(tr[lson].mn,tr[rson].cmn);
}
}
void push_down(int i)
{
if(tr[i].add!=0){
solve1(lson,tr[i].add);
solve1(rson,tr[i].add);
tr[i].add=0;
}
if(tr[i].cov!=inf){
solve(lson,tr[i].cov);
solve(rson,tr[i].cov);
tr[i].cov=inf;
}
if(tr[i].lz!=-inf){
solve2(lson,tr[i].lz);
solve2(rson,tr[i].lz);
tr[i].lz=-inf;
}
return ;
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r; tr[i].add=0; tr[i].cmn=inf;
tr[i].lz=-inf; tr[i].cov=inf; tr[i].cnt=0; tr[i].mn=inf;
if(l==r){
tr[i].mn=a[l]; tr[i].cnt=1;
return ;
}
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
push_up(i);
}
void add(int i,int l,int r,ll val)
{
//cout<<"i "<<" l "<<tr[i].l<<" r "<<tr[i].r<<" ll "<<l<<" rr "<<r<<endl;
if(tr[i].l==l&&tr[i].r==r){
solve1(i,val);
return ;
}
int mid=(tr[i].l+tr[i].r)>>1;
push_down(i);
if(r<=mid) add(lson,l,r,val);
else if(l>mid) add(rson,l,r,val);
else{
add(lson,l,mid,val);
add(rson,mid+1,r,val);
}
push_up(i);
return ;
}
void cover(int i,int l,int r,ll val)
{
if(tr[i].l==l&&tr[i].r==r){
solve(i,val);
return ;
}
int mid=(tr[i].l+tr[i].r)>>1;
push_down(i);
if(r<=mid) cover(lson,l,r,val);
else if(l>mid) cover(rson,l,r,val);
else{
cover(lson,l,mid,val);
cover(rson,mid+1,r,val);
}
push_up(i);
}
void upmax(int i,int l,int r,ll val)
{
if(tr[i].l==l&&tr[i].r==r){
if(tr[i].mn>=val) return ;
if(tr[i].cmn>val){
tr[i].mn=val;
tr[i].lz=val;
return ;
}
}
int mid=(tr[i].l+tr[i].r)>>1;
push_down(i);
if(r<=mid) upmax(lson,l,r,val);
else if(l>mid) upmax(rson,l,r,val);
else{
upmax(lson,l,mid,val);
upmax(rson,mid+1,r,val);
}
push_up(i);
}
ll ans;
void query(int i,int l,int r)
{
if(tr[i].l==l&&tr[i].r==r){
if(tr[i].mn==0) ans+=tr[i].cnt;
return ;
}
int mid=(tr[i].l+tr[i].r)>>1;
push_down(i);
if(r<=mid) query(lson,l,r);
else if(l>mid) query(rson,l,r);
else{
query(lson,l,mid);
query(rson,mid+1,r);
}
push_up(i);
}
int n,m;
int main()
{
int op,l,r;
ll val;
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
build(1,1,n);
while(m--)
{
scanf("%d %d %d",&op,&l,&r);
if(op==1){
scanf("%lld",&val);
cover(1,l,r,val);
}
else if(op==2){
scanf("%lld",&val);
//cout<<"*** "<<endl;
add(1,l,r,val);
//cout<<"*******"<<endl;
upmax(1,l,r,0);
}
else{
ans=0;
query(1,l,r);
printf("%lld\n",ans);
}
}
return 0;
}