维护一个整数序列,支持以下操作:
1 x v : 将第x个整数的值修改为v;
2 x y : 查询区间[x,y]之间的最小值;
3 x y : 查询区间[x,y]之间的最大值;
4 x y : 查询区间[x,y]内的整数和。
数据保证查询结果均在int范围之内,但中间结果是否可能溢出呢?我交的程序没考虑这个也AC了。
通过这题还发现一个奇怪的现象,用memset初始化的程序跑了2s多,而用for循环初始化的程序才跑468ms……
for循环初始化(468ms)
#include <stdio.h> #include <string.h> #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define INF 0x7fffffff #define N 100010 int D,n; int v[N],min[4*N],max[4*N],sum[4*N]; void init() { int i; for(i=1;i<2*D;i++) { min[i]=INF; max[i]=-INF; sum[i]=0; } for(D=1;D<n+2;D<<=1); for(i=1;i<=n;i++) { min[D+i]=max[D+i]=sum[D+i]=v[i]; } for(i=D-1;i^1;i--) { min[i]=MIN(min[i<<1],min[i<<1|1]); max[i]=MAX(max[i<<1],max[i<<1|1]); sum[i]=sum[i<<1]+sum[i<<1|1]; } } void update(int k,int v) { int i; min[D+k]=max[D+k]=sum[D+k]=v; for(i=D+k;i^1;i>>=1) { min[i>>1]=MIN(min[i],min[i^1]); max[i>>1]=MAX(max[i],max[i^1]); sum[i>>1]=sum[i]+sum[i^1]; } } void getmin(int x,int y) { int i=D+x-1,j=D+y+1,ret=INF; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret=MIN(ret,min[i^1]); if(j&1) ret=MIN(ret,min[j^1]); } printf("%d\n",ret); } void getmax(int x,int y) { int i=D+x-1,j=D+y+1,ret=-INF; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret=MAX(ret,max[i^1]); if(j&1) ret=MAX(ret,max[j^1]); } printf("%d\n",ret); } void getsum(int x,int y) { int i=D+x-1,j=D+y+1,ret=0; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret+=sum[i^1]; if(j&1) ret+=sum[j^1]; } printf("%d\n",ret); } int main() { int i,m,opt,x,y; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) scanf("%d",&v[i]); scanf("%d",&m); init(); for(i=0;i<m;i++) { scanf("%d%d%d",&opt,&x,&y); switch(opt) { case 1: update(x,y); break; case 2: getmin(x,y); break; case 3: getmax(x,y); break; case 4: getsum(x,y); break; } } } return 0; }
memset初始化(2s多)
#include <stdio.h> #include <string.h> #define MIN(a,b) ((a)<(b)?(a):(b)) #define MAX(a,b) ((a)>(b)?(a):(b)) #define INF 0x7fffffff #define N 100010 int D,n; int v[N],min[4*N],max[4*N],sum[4*N]; void init() { int i; memset(min,0x3f,sizeof(min)); memset(max,0xc3,sizeof(max)); memset(sum,0,sizeof(sum)); for(D=1;D<n+2;D<<=1); for(i=1;i<=n;i++) { min[D+i]=max[D+i]=sum[D+i]=v[i]; } for(i=D-1;i^1;i--) { min[i]=MIN(min[i<<1],min[i<<1|1]); max[i]=MAX(max[i<<1],max[i<<1|1]); sum[i]=sum[i<<1]+sum[i<<1|1]; } } void update(int k,int v) { int i; min[D+k]=max[D+k]=sum[D+k]=v; for(i=D+k;i^1;i>>=1) { min[i>>1]=MIN(min[i],min[i^1]); max[i>>1]=MAX(max[i],max[i^1]); sum[i>>1]=sum[i]+sum[i^1]; } } void getmin(int x,int y) { int i=D+x-1,j=D+y+1,ret=INF; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret=MIN(ret,min[i^1]); if(j&1) ret=MIN(ret,min[j^1]); } printf("%d\n",ret); } void getmax(int x,int y) { int i=D+x-1,j=D+y+1,ret=-INF; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret=MAX(ret,max[i^1]); if(j&1) ret=MAX(ret,max[j^1]); } printf("%d\n",ret); } void getsum(int x,int y) { int i=D+x-1,j=D+y+1,ret=0; for(;i^j^1;i>>=1,j>>=1) { if(~i&1) ret+=sum[i^1]; if(j&1) ret+=sum[j^1]; } printf("%d\n",ret); } int main() { int i,m,opt,x,y; while(~scanf("%d",&n)) { for(i=1;i<=n;i++) scanf("%d",&v[i]); scanf("%d",&m); init(); for(i=0;i<m;i++) { scanf("%d%d%d",&opt,&x,&y); switch(opt) { case 1: update(x,y); break; case 2: getmin(x,y); break; case 3: getmax(x,y); break; case 4: getsum(x,y); break; } } } return 0; }