Description
Input
Sample Input
10 9
3580 8597 508 9110 9162 9973 6017 1942 989 646
1 3 4 405
4 3 5
5 6 7
6 4 9
7 5 7
2 1 8 9623
5 1 6
4 2 7
3 7 7 8581
Output
Sample Output
19590
6017
9973
1
-8710
-13561
Solution
超级码农题!!!
显然线段树,第①②④⑤⑥问都可以轻易处理出来
对于第③问,只需维护一下标志数组,也不难处理
而本题的关键是第⑦问!
-
对于一个区间,记录以下一些量:
1.最左边的数
2.最右边的数
3.以最左边为起点往右延伸个数
4.以最右边为起点往左延伸个数
5.答案(最长子串) 这样合并方法就很显然了!
为处理方便也可记录区间元素个数,时间复杂度
O(Nlogn)
Code
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=100001,MX=1e9;
typedef long long LL;
struct data
{
int max,min,left,right,lnum,rnum,len,cnt;
LL sum;
}f[8*N];
int n,q,num,sum;
int a[N],c[8*N],d[8*N];
LL ans;
inline int read()
{
int data=0; char ch=0;
while(ch<'0' || ch>'9') ch=getchar();
while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();
return data;
}
inline void updata(int v)
{
int ls=2*v,rs=ls+1;
f[v].max=max(f[ls].max,f[rs].max);
f[v].min=min(f[ls].min,f[rs].min);
f[v].sum=f[ls].sum+f[rs].sum;
f[v].lnum=f[ls].lnum,f[v].rnum=f[rs].rnum;
f[v].left=f[ls].left,f[v].right=f[rs].right;
f[v].len=max(f[ls].len,f[rs].len);
if(f[ls].rnum==f[rs].lnum)
{
f[v].len=max(f[v].len,f[ls].right+f[rs].left);
if(f[ls].left==f[ls].cnt) f[v].left+=f[rs].left;
if(f[rs].right==f[rs].cnt) f[v].right+=f[ls].right;
}
}
inline void modify(int v)
{
int ls=v*2,rs=v*2+1;
if(d[v]==1)
{
f[v].max+=c[v],f[v].min+=c[v];
f[v].lnum+=c[v],f[v].rnum+=c[v];
f[v].sum+=f[v].cnt*c[v];
c[ls]+=c[v],c[rs]+=c[v];
if(!d[ls]) d[ls]=1;
if(!d[rs]) d[rs]=1;
c[v]=d[v]=0;
}else
if(d[v]==2)
{
f[v].max=f[v].min=f[v].lnum=f[v].rnum=c[v];
f[v].sum=f[v].cnt*c[v];
f[v].len=f[v].left=f[v].right=f[v].cnt;
c[ls]=c[rs]=c[v];
d[ls]=d[rs]=2;
c[v]=d[v]=0;
}
}
inline void make(int v,int l,int r)
{
if(l==r)
{
f[v].sum=f[v].max=f[v].min=f[v].lnum=f[v].rnum=a[l];
f[v].len=f[v].left=f[v].right=f[v].cnt=1;
return;
}
int mid=(l+r)>>1,ls=2*v,rs=ls+1;
make(ls,l,mid),make(rs,mid+1,r);
f[v].cnt=f[ls].cnt+f[rs].cnt;
updata(v);
}
inline void find(int v,int l,int r,int x,int y,int pd)
{
if(l==x && r==y)
{
if(pd==4) ans+=f[v].sum; else
if(pd==5) ans=min(ans,(LL)f[v].min); else ans=max(ans,(LL)f[v].max);
return;
}
int mid=(l+r)>>1,ls=2*v,rs=ls+1;
modify(ls),modify(rs);
if(y<=mid) find(ls,l,mid,x,y,pd); else
if(x>mid) find(rs,mid+1,r,x,y,pd); else
{
find(ls,l,mid,x,mid,pd);
find(rs,mid+1,r,mid+1,y,pd);
}
}
inline int find_all(int v,int l,int r,int x,int y)
{
if(l==x && r==y) return f[v].len;
int mid=(l+r)>>1,ls=2*v,rs=ls+1;
modify(ls),modify(rs);
if(y<=mid) return find_all(ls,l,mid,x,y); else
if(x>mid) return find_all(rs,mid+1,r,x,y); else
{
int sum=max(find_all(ls,l,mid,x,mid),find_all(rs,mid+1,r,mid+1,y));
if(f[ls].rnum==f[rs].lnum) sum=max(sum,min(f[ls].right,mid-x+1)+min(f[rs].left,y-mid));
return sum;
}
}
inline void change(int v,int l,int r,int x,int y,int z)
{
if(l==x && r==y)
{
c[v]=z,d[v]=1;
modify(v);
return;
}
int mid=(l+r)>>1,ls=2*v,rs=ls+1;
modify(ls),modify(rs);
if(y<=mid) change(ls,l,mid,x,y,z); else
if(x>mid) change(rs,mid+1,r,x,y,z); else
{
change(ls,l,mid,x,mid,z);
change(rs,mid+1,r,mid+1,y,z);
}
updata(v);
}
inline void change_all(int v,int l,int r,int x,int y,int z)
{
if(l==x && r==y)
{
c[v]=z,d[v]=2;
modify(v);
return;
}
int mid=(l+r)>>1,ls=2*v,rs=ls+1;
modify(ls),modify(rs);
if(y<=mid) change_all(ls,l,mid,x,y,z); else
if(x>mid) change_all(rs,mid+1,r,x,y,z); else
{
change_all(ls,l,mid,x,mid,z);
change_all(rs,mid+1,r,mid+1,y,z);
}
updata(v);
}
int main()
{
n=read(),q=read();
for(int i=1;i<=n;i++) a[i]=read();
make(1,1,n);
while(q--)
{
int t=read(),l=read(),r=read();
if(t==7) printf("%d\n",find_all(1,1,n,l,r)); else
if(t<=3)
{
int v=read();
if(t==3) change_all(1,1,n,l,r,v); else
{
if(t==2) v=-v;
change(1,1,n,l,r,v);
}
}else
{
if(t==4) ans=0; else
if(t==5) ans=MX; else ans=-MX;
find(1,1,n,l,r,t);
printf("%lld\n",ans);
}
}
return 0;
}