Segment Tree | ||
Accepted : 98 | Submit : 545 | |
Time Limit : 9000 MS | Memory Limit : 65536 KB |
Segment Tree
Problem Description:
A contest is not integrity without problems about data structure.
There is an array a[1],a[2],…,a[n]. And q questions of the following 4 types:- 1 l r c - Update a[k] with a[k]+c for all l≤k≤r
- 2 l r c - Update a[k] with min{a[k],c} for all l≤k≤r;
- 3 l r c - Update a[k] with max{a[k],c} for all l≤k≤r;
- 4 l r - Ask for min{a[k]:l≤k≤r} and max{a[k]:l≤k≤r}.
Input
The first line contains a integer T(no more than 5) which represents the number of test cases.
For each test case, the first line contains 2 integers n,q (1≤n,q≤200000).
The second line contains n integers a1,a2,…,an which indicates the initial values of the array (|ai|≤).
Each of the following q lines contains an integer t which denotes the type of i-th question. If t=1,2,3, 3 integers l,r,c follows. If t=4, 2 integers l,r follows. (1≤ti≤4,1≤li≤ri≤n)
If t=1, |ci|≤2000;
If t=2,3, |ci|≤10^9.
Output
For each question of type 4, output two integers denote the minimum and the maximum.
Sample Input
1
1 1
1
4 1 1
Sample Output
1 1
题目链接:http://202.197.224.59/OnlineJudge2/index.php/Problem/read/id/1238
题目大意:自己看;
题目分析:线段树区间更新,区间求值;
我的初始错误代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=222222;
ll minv[maxn*8],maxv[maxn*8],num[maxn*8],smin[maxn*8],smax[maxn*8],addv[maxn*8];
int n,p;
ll _maxv,_minv;
void maintain(int o,int l,int r)
{
int lc=o<<1,rc=o<<1|1;
if(l==r)
return ;
minv[o]=min(minv[lc],minv[rc]);
maxv[o]=max(maxv[lc],maxv[rc]);
}
void build(int o,int l,int r)
{
int lc=o<<1,rc=o<<1|1;
if(l==r)
{
minv[o]=maxv[o]=num[l];
return ;
}
int m=(l+r)>>1;
build(lc,l,m);
build(rc,m+1,r);
maintain(o,l,r);
}
void pushdown(int o,int l,int r)
{
if(l==r)
return ;
int lc=o<<1,rc=o<<1|1;
if(addv[o])
{
minv[lc]+=addv[o];
minv[rc]+=addv[o];
addv[lc]+=addv[o];
addv[rc]+=addv[o];
maxv[lc]+=addv[o];
maxv[rc]+=addv[o];
addv[o]=0;
}
if(smax[o])
{
smax[lc]=smax[rc]=smax[o];
minv[lc]=max(minv[lc],smax[o]); minv[rc]=max(minv[rc],smax[o]);
maxv[rc]=max(maxv[rc],smax[o]); maxv[lc]=max(maxv[lc],smax[o]);
smax[o]=0;
}
if(smin[o])
{
smin[lc]=smin[rc]=smin[o];
minv[lc]=min(minv[lc],smin[o]); minv[rc]=min(minv[rc],smin[o]);
maxv[rc]=min(maxv[rc],smin[o]); maxv[lc]=min(maxv[lc],smin[o]);
smin[o]=0;
}
}
void unreduce(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
pushdown(o,l,r);
if(l>=L&&r<=R)
{
smax[o]=c;
minv[o]=max(minv[o],c);
maxv[o]=max(maxv[o],c);
return ;
}
if(L<=m)
unreduce(lc,l,m,L,R,c);
if(R>m)
unreduce(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void reduce(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
pushdown(o,l,r);
if(l>=L&&r<=R)
{
smin[o]=c;
minv[o]=min(minv[o],c);
maxv[o]=min(maxv[o],c);
return ;
}
if(L<=m)
reduce(lc,l,m,L,R,c);
if(R>m)
reduce(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void add(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
pushdown(o,l,r);
if(l>=L&&r<=R)
{
addv[o]+=c;
minv[o]+=c;
maxv[o]+=c;
return ;
}
if(L<=m)
add(lc,l,m,L,R,c);
if(R>m)
add(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void query(int o,int l,int r,int L,int R)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
pushdown(o,l,r);
if(l>=L&&r<=R)
{
_minv=min(_minv,minv[o]);
_maxv=max(_maxv,maxv[o]);
return ;
}
if(L<=m)
query(lc,l,m,L,R);
if(R>m)
query(rc,m+1,r,L,R);
maintain(o,l,r);
}
int main()
{
int T;
while(scanf("%d",&T)!=EOF)
while(T--)
{
memset(addv,0,sizeof(addv));
memset(smin,0,sizeof(smin));
memset(smax,0,sizeof(smax));
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&num[i]);
}
build(1,1,n);
int l,r;
ll c;
for(int i=0;i<p;i++)
{
int t;
scanf("%d%d%d",&t,&l,&r);
if(t==4)
{
_minv=1e12+7;
_maxv=-1e12+7;
query(1,1,n,l,r);
printf("%I64d %I64d\n",_minv,_maxv);
continue;
}
scanf("%I64d",&c);
if(t==1)
{
add(1,1,n,l,r,c);
}
if(t==2)
{
reduce(1,1,n,l,r,c);
}
if(t==3)
{
unreduce(1,1,n,l,r,c);
}
}
}
return 0;
}
这份代码错误的地方有:
当操作2,3时,有覆盖操作;
比如有smax[lr]本身有值的时候,再赋予smax[lc]值时会产生覆盖,造成错误;
参考修改代码:
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=222222;
ll minv[maxn*8],maxv[maxn*8],num[maxn*8],addv[maxn*8];
int n,p;
ll _maxv,_minv;
void maintain(int o,int l,int r)
{
int lc=o<<1,rc=o<<1|1;
if(l==r)
return ;
minv[o]=min(minv[lc],minv[rc]);
maxv[o]=max(maxv[lc],maxv[rc]);
}
void build(int o,int l,int r)
{
int lc=o<<1,rc=o<<1|1;
if(l==r)
{
minv[o]=maxv[o]=num[l];
return ;
}
int m=(l+r)>>1;
build(lc,l,m);
build(rc,m+1,r);
maintain(o,l,r);
}
void pushdown(int o,int l,int r)
{
int lc=o<<1,rc=lc+1;
if(addv[o])
{
minv[lc]+=addv[o];
minv[rc]+=addv[o];
addv[lc]+=addv[o];
addv[rc]+=addv[o];
maxv[lc]+=addv[o];
maxv[rc]+=addv[o];
addv[o]=0;
}
minv[lc]=max(minv[o],minv[lc]);minv[lc]=min(maxv[o],minv[lc]);
maxv[lc]=min(maxv[o],maxv[lc]);maxv[lc]=max(minv[o],maxv[lc]);
maxv[rc]=min(maxv[o],maxv[rc]);maxv[rc]=max(minv[o],maxv[rc]);
minv[rc]=max(minv[o],minv[rc]);minv[rc]=min(maxv[o],minv[rc]);
}
void unreduce(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
if(l>=L&&r<=R)
{
maxv[o]=max(maxv[o],c);
minv[o]=max(minv[o],c);
return ;
}
pushdown(o,l,r);
if(L<=m)
unreduce(lc,l,m,L,R,c);
if(R>m)
unreduce(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void reduce(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
if(l>=L&&r<=R)
{
minv[o]=min(minv[o],c);
maxv[o]=min(maxv[o],c);
return ;
}
pushdown(o,l,r);
if(L<=m)
reduce(lc,l,m,L,R,c);
if(R>m)
reduce(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void add(int o,int l,int r,int L,int R,ll c)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
if(l>=L&&r<=R)
{
addv[o]+=c;
minv[o]+=c;
maxv[o]+=c;
return ;
}
pushdown(o,l,r);
if(L<=m)
add(lc,l,m,L,R,c);
if(R>m)
add(rc,m+1,r,L,R,c);
maintain(o,l,r);
}
void query(int o,int l,int r,int L,int R)
{
int m=(l+r)>>1;
int lc=o<<1,rc=o<<1|1;
if(l>=L&&r<=R)
{
_minv=min(_minv,minv[o]);
_maxv=max(_maxv,maxv[o]);
return ;
}
pushdown(o,l,r);
if(L<=m)
query(lc,l,m,L,R);
if(R>m)
query(rc,m+1,r,L,R);
maintain(o,l,r);
}
int main()
{
int T;
while(scanf("%d",&T)!=EOF)
while(T--)
{
memset(addv,0,sizeof(addv));
scanf("%d%d",&n,&p);
for(int i=1;i<=n;i++)
{
scanf("%I64d",&num[i]);
}
build(1,1,n);
int l,r;
ll c;
for(int i=0;i<p;i++)
{
int t;
scanf("%d%d%d",&t,&l,&r);
if(t==4)
{
_minv=1e12+7;
_maxv=-1e12+7;
query(1,1,n,l,r);
printf("%I64d %I64d\n",_minv,_maxv);
continue;
}
scanf("%I64d",&c);
if(t==1)
{
add(1,1,n,l,r,c);
}
if(t==2)
{
reduce(1,1,n,l,r,c);
}
if(t==3)
{
unreduce(1,1,n,l,r,c);
}
}
}dai
return 0;
}