区间最值差
作者:互联网
链接:http://poj.org/problem?id=3468
难度不大,注意细节
1 #include<cstdio> //分块,poj3468 2 #include<algorithm> 3 #include<cmath> 4 #define ll long long 5 #define N 100010 6 using namespace std; 7 ll a[N],sum[N],add[N]; 8 int L[N],R[N],d; 9 int pos[N]; 10 int n,m,l,r; 11 char op[3]; 12 13 void build(){//分块预处理 14 int t=sqrt(n*1.0);//float sqrt (float),double sqrt (double),double long sqrt(double long) 15 int num=n/t; 16 if(n%t) num++; 17 for(int i=1;i<=num;i++){ 18 L[i]=(i-1)*t+1;//每块的左右端点 19 R[i]=i*t; 20 } 21 R[num]=n; //最后一块的右端点为n 22 for(int i=1;i<=num;i++) 23 for(int j=L[i];j<=R[i];j++){ 24 pos[j]=i; //表示第j个元素属于第i块 25 sum[i]+=a[j]; //计算每块和值 26 } 27 } 28 29 void change(int l,int r,long long d){//区间更新,[l,r]区间的元素加上d 30 int p=pos[l],q=pos[r];//读所属块 31 if(p==q){//在一块中 32 for(int i=l;i<=r;i++)//暴力修改 33 a[i]+=d; 34 sum[p]+=d*(r-l+1);//修改和值 35 } 36 else{ 37 for(int i=p+1;i<=q-1;i++)//中间完全覆盖块打懒标记 38 add[i]+=d; 39 for(int i=l;i<=R[p];i++)//左端暴力修改 40 a[i]+=d; 41 sum[p]+=d*(R[p]-l+1); 42 for(int i=L[q];i<=r;i++)//右端暴力修改 43 a[i]+=d; 44 sum[q]+=d*(r-L[q]+1);//修改和值 45 } 46 } 47 48 ll query(int l,int r){//区间查询,查询[l,r]区间的元素和值 49 int p=pos[l],q=pos[r]; 50 ll ans=0; 51 if(p==q){//在一块中 52 for(int i=l;i<=r;i++)//累加 53 ans+=a[i]; 54 ans+=add[p]*(r-l+1);//计算懒标记 55 } 56 else{ 57 for(int i=p+1;i<=q-1;i++)//累加中间块 58 ans+=sum[i]+add[i]*(R[i]-L[i]+1); 59 for(int i=l;i<=R[p];i++)//左端暴力累加 60 ans+=a[i]; 61 ans+=add[p]*(R[p]-l+1); 62 for(int i=L[q];i<=r;i++)//右端暴力累加 63 ans+=a[i]; 64 ans+=add[q]*(r-L[q]+1);//计算懒标记 65 } 66 return ans; 67 } 68 69 int main(){ 70 scanf("%d%d",&n,&m); 71 for(int i=1;i<=n;i++) 72 scanf("%lld",&a[i]); 73 build(); 74 for(int i=1;i<=m;i++){ 75 scanf("%s %d %d",op,&l,&r); 76 if(op[0]=='C'){ 77 scanf("%d",&d); 78 change(l,r,d); 79 } 80 else 81 printf("%lld\n",query(l,r)); 82 } 83 return 0; 84 }
标签:int,double,float,long,sqrt,区间,include,最值 来源: https://www.cnblogs.com/tflsnoi/p/16177909.html