0x03 前缀和与差分

前缀和

【例题】BZOJ1218 激光炸弹

计算二位前缀和,再利用容斥原理计算出答案即可。

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 using namespace std;
 6 const int maxn=5000+10;
 7 int n, r, sum[maxn][maxn];
 8 
 9 int main() {
10     scanf("%d%d", &n, &r);
11     int x, y, v, maxx=0, maxy=0;
12     maxx=maxy=r;
13     for (int i=1; i<=n; ++i) {
14         scanf("%d%d%d", &x, &y, &v);
15         ++x; ++y;
16         maxx=max(maxx, x); maxy=max(maxy, y);
17         sum[x][y]=v;
18     }
19     for (int i=1; i<=maxx; ++i) {
20         for (int j=1; j<=maxy; ++j) {
21             sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
22         }
23     }
24     //枚举面积为r的正方形
25     int ans=0;
26     for (int i=r; i<=maxx; ++i) {
27         for (int j=r; j<=maxy; ++j) {
28             ans=max(ans, sum[i][j]-sum[i-r][j]-sum[i][j-r]+sum[i-r][j-r]);
29         }
30     } 
31     printf("%d\n", ans);
32     return 0;
33 }

差分

【例题】CH0304 IncDec Sequence

求出序列a的差分序列b,令bn+1=0,目标是将把b2,b3...bn变为全0。

把序列a区间[l,r]加d,其差分序列的变化为Bl加d,Br+1减d。

从b1,b2...bn中任选两个数的方法可以分为4类:

1.选bi和bj

2.选b1和bj

3.选bi和bn+1

4.选b1和bn+1,这种选法没有意义

设整数总和为p,负数总和为q,首先以正负数匹配的方式尽量选择操作1,可执行min(p,q)次。

剩余|p-q|个未配对,执行操作2和操作3,共需|p-q|次。

所以最少操作次数为min(p,q)+|p-q|=max(p,q)次,根据操作2,3的选择情况,能产生|p-q|+1种b1的值,即序列a可能有|p-q|+1种。

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 #include 
 6 using namespace std;
 7 const int maxn=100000+10;
 8 long long n, a[maxn], s[maxn], p=0, q=0;
 9 
10 int main() {
11     scanf("%lld", &n);
12     for (int i=1; i<=n; ++i)
13         scanf("%lld", &a[i]);
14     s[1]=a[1]; s[n+1]=0;
15     for (int i=2; i<=n; ++i) {
16         s[i]=a[i]-a[i-1];
17     }
18     for (int i=2; i<=n; ++i) {
19         if (s[i]>0) p+=s[i];
20         else if (s[i]<0) q-=s[i];
21     }
22     printf("%lld\n%lld\n", max(p,q), abs(p-q)+1);
23     return 0;
24 }

【例题】POJ3263 Tallest Cow

若有一条关系指明Ai和Bi可以互相看见,就将他们数组中Ai+1到Bi-1的数减去1,最终得到所有牛与最高的牛p的相对身高关系。

 1 #include 
 2 #include 
 3 #include 
 4 #include 
 5 #include 
 6 #include 
 7 using namespace std;
 8 const int maxn=100000+10;
 9 int n, p, h, m, c[maxn], d[maxn];
10 mapint, int>, bool> ext;
11 
12 int main() {
13     scanf("%d%d%d%d", &n, &p, &h, &m);
14     int a, b;
15     for (int i=1; i<=m; ++i) {
16         scanf("%d%d", &a, &b);
17         if (a>b) swap(a,b);
18         if (ext[make_pair(a,b)]) continue;
19         d[a+1]--, d[b]++;
20         ext[make_pair(a,b)]=true;
21     }
22     for (int i=1; i<=n; ++i) {
23         c[i]=c[i-1]+d[i];
24         printf("%d\n", h+c[i]);
25     }
26     return 0;
27 }

 

你可能感兴趣的:(0x03 前缀和与差分)