A Simple Problem with Integers POJ - 3468 (分块)
题目链接:https://cn.vjudge.net/problem/POJ-3468
题目大意:区间加减+区间查询操作。
具体思路:本来是一个线段树裸题,为了学习分块就按照分块的方法做吧。
分块真的好暴力,,,(但是还是挺优美的)。
说一下各个数组的作用。
a数组,代表每一个点的值。
sum数组,代表分块后每一段的值。
add数组,相当于线段树中的lazy标记,记录的数当前这一整段添加的值。
l数组,r数组,记录每一段的左端点和右端点。
belong数组,记录每一个数属于哪一个分块中。
AC代码:
1 #include<iostream> 2 #include<stack> 3 #include<string> 4 #include<stdio.h> 5 #include<algorithm> 6 #include<cmath> 7 #include<math.h> 8 using namespace std; 9 # define ll long long 10 const int maxn = 1e6+100; 11 ll a[maxn],sum[maxn],add[maxn]; 12 int l[maxn],r[maxn]; 13 int belong[maxn]; 14 void buildblock(int t){ 15 int tmp=(int)sqrt(t*1.0); 16 int tot=t/tmp; 17 if(t%tmp)tot++; 18 for(int i=1;i<=t;i++){ 19 belong[i]=(i-1)/tmp+1; 20 } 21 for(int i=1;i<=tot;i++){ 22 l[i]=(i-1)*tmp+1; 23 r[i]=i*tmp; 24 } 25 r[tot]=t; 26 for(int i=1;i<=tot;i++){ 27 for(int j=l[i];j<=r[i];j++){ 28 sum[i]+=a[j]; 29 } 30 } 31 } 32 void update(int st,int ed,ll val){ 33 if(belong[st]==belong[ed]){ 34 for(int i=st;i<=ed;i++){ 35 a[i]+=val; 36 sum[belong[st]]+=val; 37 } 38 return ; 39 } 40 for(int i=st;i<=r[belong[st]];i++){ 41 a[i]+=val; 42 sum[belong[st]]+=val; 43 } 44 for(int i=l[belong[ed]];i<=ed;i++){ 45 a[i]+=val; 46 sum[belong[ed]]+=val; 47 } 48 for(int i=belong[st]+1;i<belong[ed];i++){ 49 add[i]+=val; 50 } 51 } 52 ll ask(int st,int ed){ 53 ll ans=0; 54 if(belong[st]==belong[ed]){ 55 for(int i=st;i<=ed;i++){ 56 ans+=a[i]+add[belong[st]]; 57 } 58 return ans; 59 } 60 for(int i=st;i<=r[belong[st]];i++){ 61 ans+=a[i]+add[belong[st]]; 62 } 63 for(int i=l[belong[ed]];i<=ed;i++){ 64 ans+=a[i]+add[belong[ed]]; 65 } 66 for(int i=belong[st]+1;i<belong[ed];i++){ 67 ans+=sum[i]+add[i]*(r[i]-l[i]+1); 68 } 69 return ans; 70 } 71 int main(){ 72 //freopen("hqx.in","r",stdin); 73 int n,m; 74 scanf("%d %d",&n,&m); 75 for(int i=1;i<=n;i++){ 76 scanf("%lld",&a[i]); 77 } 78 buildblock(n); 79 char str[10]; 80 int st,ed; 81 ll cost; 82 while(m--){ 83 scanf("%s",str); 84 if(str[0]=='Q'){ 85 scanf("%d %d",&st,&ed); 86 printf("%lld\n",ask(st,ed)); 87 } 88 else if(str[0]=='C'){ 89 scanf("%d %d %lld",&st,&ed,&cost); 90 update(st,ed,cost); 91 } 92 } 93 return 0; 94 }