給定一個長度爲n(n<=100000),初始值都爲0的序列,x(x<=10000)次的修改某些位置上的數字,每次加上一個數,而後提出y (y<=10000)個問題,求每段區間的和。時間限制1秒。php
輸入格式:ios
第一行1個數,表示序列的長度nide
第二行1個數,表示操做的次數wspa
後面依次是w行,分別表示加入和詢問操做3d
其中,加入用x表示,詢問用y表示code
x的格式爲"x a b" 表示在序列a的位置加上borm
y的格式爲"y a b" 表示詢問a到b區間的加和blog
輸出格式:ci
每行一個數,分別是每次詢問的結果element
5 4 x 3 8 y 1 3 x 4 9 y 3 4
8 17
簡單的單點更新區間求和
代碼:
//編號從1開始 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXN=100000; int n,m,sn,val[MAXN+9],pie[MAXN+9]; void add(int x,int y) { val[x]+=y;pie[x/sn]+=y; } int query(int x,int y) { int ans=0,xp=(x-1)/sn+1,yp=(y-1)/sn+1; for(int i=x;i<=min(xp*sn,y);i++) ans+=val[i]; if(xp!=yp) for(int i=(yp-1)*sn+1;i<=y;i++) ans+=val[i]; for(int i=xp+1;i<=yp-1;i++) ans+=pie[i]; return ans; } int main() { memset(val,0,sizeof(val)); memset(pie,0,sizeof(pie)); scanf("%d%d",&n,&m); sn=sqrt(n); char ch[2]; int x,y; while(m--){ scanf("%s%d%d",ch,&x,&y); if(ch[0]=='x') add(x,y); else printf("%d\n",query(x,y)); } return 0; }
Time Limit: 2 second(s) | Memory Limit: 64 MB |
World is getting more evil and it's getting tougher to get into the Evil League of Evil. Since the legendary Bad Horse has retired, now you have to correctly answer the evil questions of Dr. Horrible, who has a PhD in horribleness (but not in Computer Science). You are given an array of n elements, which are initially all 0. After that you will be given q commands. They are -
The array is indexed from 0 to n - 1.
Input starts with an integer T (≤ 5), denoting the number of test cases.
Each case contains two integers n (1 ≤ n ≤ 105) and q (1 ≤ q ≤ 50000). Each of the next q lines contains a task in one of the following form:
0 x y v (0 ≤ x ≤ y < n, 1 ≤ v ≤ 1000)
1 x y (0 ≤ x ≤ y < n)
For each case, print the case number first. Then for each query '1 x y', print the sum of all the array elements between x and y.
Sample Input |
Output for Sample Input |
2 10 5 0 0 9 10 1 1 6 0 3 7 2 0 4 5 1 1 5 5 20 3 0 10 12 1 1 11 12 1 19 19 |
Case 1: 60 13 Case 2: 2 0 |
Dataset is huge. Use faster i/o methods.
題意:
0 x y z 表示x~y區間每一個數加z
1 x y 表示詢問區間和
最初每一個點初值爲0
代碼:
//區間更新,區間求和。 //這題的詢問變成了區間上的詢問,不完整的塊仍是暴力;而要想快速統計完整塊的答案,須要維護每一個塊的元素和, //先要預處理一下。 //考慮區間修改操做,不完整的塊直接改,順便更新塊的元素和;完整的塊相似以前標記的作法, //直接根據塊的元素和所加的值計算元素和的增量。 #include<iostream> #include<cstdio> #include<cstring> #include<cmath> using namespace std; typedef long long ll; const int MAXN=100000; int t,n,m,sn; ll val[MAXN+9],tag[MAXN+9],sum[MAXN+9]; void add(int x,int y,int z) { int xb=(x-1)/sn+1,yb=(y-1)/sn+1; for(int i=x;i<=min(xb*sn,y);i++) val[i]+=z,sum[xb]+=z; if(xb!=yb) for(int i=(yb-1)*sn+1;i<=y;i++) val[i]+=z,sum[yb]+=z; for(int i=xb+1;i<=yb-1;i++) tag[i]+=z; } ll query(int x,int y) { int xb=(x-1)/sn+1,yb=(y-1)/sn+1; ll ans=0; for(int i=x;i<=min(xb*sn,y);i++) ans+=val[i]+tag[xb]; if(xb!=yb) for(int i=(yb-1)*sn+1;i<=y;i++) ans+=val[i]+tag[yb]; for(int i=xb+1;i<=yb-1;i++) ans+=tag[i]*sn+sum[i]; return ans; } int main() { scanf("%d",&t); for(int cas=1;cas<=t;cas++){ printf("Case %d:\n",cas); scanf("%d%d",&n,&m); sn=sqrt(n); memset(val,0,sizeof(val)); memset(tag,0,sizeof(tag)); memset(sum,0,sizeof(sum)); int p,x,y,z; while(m--){ scanf("%d",&p); if(p==0){ scanf("%d%d%d",&x,&y,&z); add(x+1,y+1,z); }else{ scanf("%d%d",&x,&y); printf("%lld\n",query(x+1,y+1)); } } } return 0; }