没想到线段树的基本用法这么长时间没写了还没有忘,1A的感觉还是很爽的。
题目大意:
中文题,点此查看题目。
解题思路:
线段树的区间更新与查询。
lazy标记的使用。
当需要返回区间多个值时可以使用引用参数。
下面是代码:
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <stdlib.h>
using namespace std;
int min(int a,int b)
{
if(a>b)a=b;
return a;
}
int max(int a,int b)
{
if(a<b)a=b;
return a;
}
int n,m,l,r,x;
struct node1
{
int num,l,r,lcnt,rcnt,mcnt;
} node[100000<<2];
char s[3];
void PushUp(int l,int r,int m,int tr)
{
node[tr].num=-1;
node[tr].l=node[tr<<1].l;
node[tr].r=node[tr<<1|1].r;
node[tr].lcnt=node[tr<<1].lcnt;
if(node[tr<<1].lcnt==m-l+1&&node[tr<<1].r<node[tr<<1|1].l)
{
node[tr].lcnt+=node[tr<<1|1].lcnt;
}
node[tr].rcnt=node[tr<<1|1].rcnt;
if(node[tr<<1|1].rcnt==r-m&&node[tr<<1].r<node[tr<<1|1].l)
{
node[tr].rcnt+=node[tr<<1].rcnt;
}
if(node[tr<<1].r<node[tr<<1|1].l)
{
node[tr].mcnt=node[tr<<1].rcnt+node[tr<<1|1].lcnt;
}
else node[tr].mcnt=0;
node[tr].mcnt=max(node[tr<<1].mcnt,max(node[tr<<1|1].mcnt,max(node[tr].lcnt,max(node[tr].rcnt,node[tr].mcnt))));
}
void build(int l,int r,int tr)
{
if(l==r)
{
scanf("%d",&node[tr].num);
node[tr].l=node[tr].num;
node[tr].r=node[tr].num;
node[tr].lcnt=1;
node[tr].rcnt=1;
node[tr].mcnt=1;
return ;
}
int m=(l+r)>>1;
build(l,m,tr<<1);
build(m+1,r,tr<<1|1);
PushUp(l,r,m,tr);
}
void Pushdown(int l,int r,int tr)
{
if(node[tr].num!=-1)
{
node[tr<<1]=node[tr];
node[tr<<1|1]=node[tr];
node[tr].num=-1;
}
}
void Update(int L,int R,int num,int l,int r,int tr)
{
if(L<=l&&r<=R)
{
if(node[tr].num==-1)node[tr].num=0;
node[tr].num+=num;
node[tr].l=num;
node[tr].r=num;
node[tr].lcnt=1;
node[tr].rcnt=1;
node[tr].mcnt=1;
return ;
}
if(l==r)return;
Pushdown(l,r,tr);
int m=(l+r)>>1;
if(m>=L)Update(L,R,num,l,m,tr<<1);
if(m<R)Update(L,R,num,m+1,r,tr<<1|1);
PushUp(l,r,m,tr);
}
void copy1(int a,int b,int c,int d,int e,int &a1,int &b1,int &c1,int &d1,int &e1)
{
a1=a;
b1=b;
c1=c;
d1=d;
e1=e;
}
void query(int L,int R,int l,int r,int tr,int &lcnt,int &lnum,int &rcnt,int &rnum,int &mnum)
{
if(L<=l&&r<=R)
{
mnum=node[tr].mcnt;
lcnt=node[tr].lcnt;
lnum=node[tr].l;
rcnt=node[tr].rcnt;
rnum=node[tr].r;
return;
}
if(l==r)return;
int m=(l+r)>>1,a[2]={0},b[2]={0},c[2]={0},d[2]={0},e[2]={0};
Pushdown(l,r,tr);
if(m>=L)
{
query(L,R,l,m,tr<<1,a[0],b[0],c[0],d[0],e[0]);
}
if(m<R)
{
query(L,R,m+1,r,tr<<1|1,a[1],b[1],c[1],d[1],e[1]);
}
if(c[0]!=0)
{
if(a[1]!=0)
{
mnum=max(e[0],e[1]);
lcnt=a[0];
lnum=b[0];
rcnt=c[1];
rnum=d[1];
if(d[0]<b[1])
{
mnum=max(mnum,c[0]+a[1]);
if(a[0]==e[0]&&a[0]==m-l+1)
{
lcnt+=a[1];
}
if(c[1]==e[1]&&c[1]==r-m)
{
rcnt+=c[0];
}
}
}
else
{
copy1(a[0],b[0],c[0],d[0],e[0],lcnt,lnum,rcnt,rnum,mnum);
}
}
else
{
copy1(a[1],b[1],c[1],d[1],e[1],lcnt,lnum,rcnt,rnum,mnum);
}
PushUp(l,r,m,tr);
return ;
}
int main()
{
scanf("%d%d",&n,&m);
build(1,n,1);
int temp[5];
for(int i=0; i<m; i++)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&l,&r);
query(l,r,1,n,1,temp[0],temp[1],temp[2],temp[3],temp[4]);
printf("%d\n",max(temp[0],max(temp[2],temp[4])));
}
else if(s[0]=='U')
{
scanf("%d%d%d",&l,&r,&x);
Update(l,r,x,1,n,1);
}
}
return 0;
}