2.尺取,差分,前缀和题解

Warning!!!!Waring

本期马蜂怪异,请空腹观看

强者从不抱怨环境(bushi

image

A. 最大的和

时间:1s 空间:256M

题目描述:

输入长度为 n 的数组 A ,求数组 A 中所有长度为 m 的区间里,区间和最大的那个区间的区间和。(数组中可能出现负数)

输入格式:

第一行两个整数 n 和 m

第二行给出 n 个整数,第i个整数代表Ai

1<=n<= 10^5 ,1<=m<=n,-10000<=Ai <=10000

输出格式:

输出一行答案,最大的区间长度为 m 的区间和

样例输入1:

5 3 
2 5 -4 10 3

样例输出1:

11

基础题

for(int j=1;j<=m;j++){
    	ans+=a[j]; 
	}
	maxn=max(maxn,ans);
    for(int i=2;i<=n;i++){
    	if(i+m-1<=n){
    		ans-=a[i-1];
    		ans+=a[i+m-1];
    		maxn=max(maxn,ans);
		} 
	}

B. 玉米地

题目描述:

小 Q 买下了一片农场,并在其中种下了 n 行 m 列玉米。

每株玉米的产量各不相同,减掉成本之后有盈有亏。具体而言,第 i 行第 j 列的玉米的收益为 ai,j,若 ai,j<0 则意味着这株玉米亏本了。

现在小 Q 想知道玉米地的收益如何。

小 Q 给了你 q 组询问,每组询问都给出四个数 x1, y1, x2, y2,需要你求出行从 x1 到 x2、列从 y1 到 y2 这个矩形区域内玉米的收益之和。

输入格式:

第一行输入三个正整数 n,m,q。

接下来 n 行,每行 m 个整数,分别表示每一株玉米的收益。

接下来 q 行,每行 4 个整数 x1, y1, x2, y2,含义如上。

输出格式:

输出 q 行,每行一个数,表示所询问的矩形区域内的玉米收益之和。

样例输入:

3 4 2
1 2 3 4
-5 6 -7 8
9 0 -1 -2
1 1 2 3
2 3 3 4

样例输出:

0 
-2

数据规模:

对于 100% 的数据,1≤n,m≤3×103,1≤q≤105,-1000≤ai,j≤1000。

差分基础题

 for(int i=1;i<=n;i++){
7
        for(int j=1;j<=m;j++){
8
            scanf("%d",&a);
9
            sum[i][j] = sum[i-1][j] + sum[i][j-1] - sum[i-1][j-1] + a;          
10
        }
11
    }
12
    while(q--){
13
        int x1,y1,x2,y2;
14
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
15
        printf("%d\n",sum[x2][y2] - sum[x1-1][y2] - sum[x2][y1-1] + sum[x1-1][y1-1]);
16
    }

C. 街区建设

Problem ID: 8524

Contest ID: 5874

必做题

Accepted

100 分

题目描述:

开发商小 Q 买下了一条街,他想在这条街的一边盖房子。

街道可以抽象为一条数轴,而小 Q 只会在坐标在 1~n 的范围内盖房子。

首先,小 Q 将街上坐标在 1~n 范围内的物体全部铲平。也就是说,在正式动工盖房子之前,1~n 范围内是没有东西的。

小 Q 的盖房子技术出奇的烂,他每次只会在坐标从 l 到 r 的一段区间上砌一堵高为 h 厘米的墙。如果某个位置已经有墙了,那么他会将墙加高 h 厘米。

好吧小 Q 不得不承认自己不会盖房子只会砌墙。

小 Q 已经砌了 m 次墙了,整条街已经乱七八糟的了。

你知道有多乱吗?

输入格式:

第一行输入两个正整数 n,m,分别表示坐标最大范围、操作总数。

接下来 m 行每行输入三个正整数 li, ri, hi,表示小 Q 在坐标从 li 到 ri 这一段区间上砌了一堵高为 hi 厘米的墙。

输出格式:

输出一行 n 个数,分别表示 m 次操作之后街道上坐标从 1 到 n 的位置上墙的高度(单位为厘米)。

样例输入:

5 3 1 3 2 2 3 1 4 4 9

样例输出:

2 3 3 9 0

数据规模:

对于 10% 的数据,m=0;

对于 100% 的数据,1≤n,m≤5×10^5,1≤h≤1000。

d[l]+=h;
        d[r+1]-=h;

D. 大哈贴广告

Problem ID: 9891

Contest ID: 5874

必做题

Accepted

100 分

时间:1s 空间:256M

题目描述:

大哈有一面 n * n 的广告墙,他往墙上贴 m 张广告,广告之间有些部分会相互重叠,问墙上的每个点上覆盖了几张广告

输入格式:

第一行两个整数 n 和 m

接下来 m 行 ,每行给出 x1 ,y1 , x2 , y2 ,代表这张广告的左上角是(x1,y1)和右下角是(x2,y2)

1≤n,m≤3000,

1≤x1≤x2≤n,

1≤y1≤y2≤n

输出格式:

输出 n 行,每行 n 个正整数,

第 i 行 第 j 个 表示 (i , j) 这个点被几张广告覆盖

样例输入1:

5 3 2 2 3 3 3 3 5 5 1 2 1 4

样例输出1:

0 1 1 1 0 0 1 1 0 0 0 1 2 1 1 0 0 1 1 1 0 0 1 1 1``

d[x1][yy]++;
9
        d[x2+1][y2+1]++;
10
        d[x2+1][yy]--;
11
        d[x1][y2+1]--;

E. 连续子区间的和

Problem ID: 15648

Contest ID: 5874

必做题

Accepted

100 分

时间:1s 空间:512M

题目描述:

有一个长度为n的不递减数组,给定一个数m,求出其中有多少连续的子区间的和等于m。

题目输入;

输入第一行,一个整数n,一个整数m

第二行,输入n个整数A[1]~A[n];

题目输出:

输出一个整数

样例输入:

5 5 1 2 3 5 6

样例输出:

2

数据范围:

n<=100000

0<= m <= 1e9

0<= A[i] <= 100000;

  while (right < n)
17
    {
18
        sum += a[right];
19
        while (sum > m) sum -= a[left ++ ];
20
        if (sum == m) res ++ ;
21
        right ++ ;
22
    }

G. 长度最小的子数组

Problem ID: 8091

Contest ID: 5874

必做题

Accepted

100 分

时间:1s 空间:256M

题目描述:

给定一个含有 n 个整数的数组和一个整数 s ,找出该数组中满足其和 ≥s 的长度最小的连续子数组。

如果不存在符合条件的连续子数组,输出 0。

输入格式:

第一行包含一个整数 T,表示测试数据组数。

对于每组测试数据,

第一行包含两个整数 n, s。

接下来包含 n 个整数 ai

输出格式:

对于每组测试数据,输出一个整数表示答案。

样例1输入:

3 8 7 2 3 1 2 0 4 3 0 8 100 2 3 1 2 0 4 3 0 3 0 1 1 1

样例1输出:

2 0 1

约定与提示:

对于100%的数据,

1≤T≤3⋅105,

1≤n≤3⋅105,

0≤s≤1018,

0≤ai≤109

保证 ∑n≤3⋅105

对于样例1的第一组测试数据:子数组下标是[6,7],所以答案为 2。

while(sum<s&&j<=n){         
13
        sum+=a[j];
14
        j++;                
15
    }
16
    if(sum>=s) minn=min(minn,j-i);  
17
    sum-=a[i];      
18
    }

H. 激光炸弹

Problem ID: 7557

Contest ID: 5874

必做题

Accepted

100 分

时间:1s 空间:256M

题目描述

一种新型的激光炸弹,可以摧毁一个边长为R的正方形内的所有的目标。现在地图上有n(N<=10000)个目标,用整数Xi,Yi(其值在[0,5000])表示目标在地图上的位置,每个目标都有一个价值vi。

激光炸弹的投放是通过卫星定位的,但其有一个缺点,就是其爆破范围,即那个边长为R的正方形的边必须和x,y轴平行。若目标位于爆破正方形的边上,该目标将不会被摧毁。

输入格式

第一行为正整数n和正整数R,接下来的n行每行有3个正整数,分别表示xi,yi,vi

输出格式

输出文件仅有一个正整数,表示一颗炸弹最多能炸掉地图上总价值为多少的目标(结果不会超过32767)。

样例输入

2 1 0 0 1 1 1 1

样例输出

1

约定

提示

 for(int i=1;i<=n;i++)
11
        {
12
                int x,y,w;
13
                cin>>x>>y>>w;
14
                x++;
15
                y++;
16
                sum[x][y]+=w;
17
                nx=max(nx,x);
18
                ny=max(ny,y);
19
        }
20
        for(int i=1;i<=nx;i++)
21
          for(int j=1;j<=ny;j++)
22
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];
23
        
24
        int s=0;
25
        for(int i=r;i<=nx;i++)
26
         for(int j=r;j<=ny;j++)
27
          s=max(s,sum[i][j]-sum[i-r][j]-sum[i][j-r]+sum[i-r][j-r]);
28
        cout<<s;

I. 矩阵翻转

Problem ID: 8167

Contest ID: 5874

必做题

Accepted

100 分

题目描述:

读入一个n*m的01矩阵,q次操作,每次将一个子矩阵内的01翻转,求最终的矩阵

输入格式:

第一行三个整数n,m,q

之后n行每行m个整数0或1

之后q行,每行四个整数x1,y1,x2,y2,表示要翻转矩阵的左上角和右下角

输出格式:

输出一个矩阵表示答案

样例输入 1

5 4 1

1 1 0 0

1 0 0 0

0 0 1 1

1 1 1 1

1 0 1 0

2 2 5 3

样例输出 1

1 1 0 0

1 1 1 0

0 1 0 1

1 0 0 1

1 1 0 0

约定:

1 ≤ n,m ≤ 500, q ≤ 1000000

提示:

for(int i=1;i<=n;i++){
19
        for(int j=1;j<=m;j++){
20
            if(i>1)d[i][j]+=d[i-1][j];
21
            if(j>1)d[i][j]+=d[i][j-1];
22
            if(i>1&&j>1)d[i][j]-=d[i-1][j-1];
23
            a[i][j]^=(d[i][j]&1);
24
            printf("%d ",a[i][j]);
25
        }
26
        printf("\n");
27
    }

J. 小李的遗迹之旅

Problem ID: 8526

Contest ID: 5874

选做题

Accepted

100 分

题目描述:

小李是一名探险家,这天,他到了一个古代遗迹当中,但是这个遗迹的大门无法打开,但是这个古代遗迹非常的神奇,在大门上不断的闪过一些古代文字,小李的探险经验非常丰富,找到了一块石碑,石碑上记载了破解大门打开的方法

破解规则如下:

石碑上给出了一些古代文字,那些古代文字其实包含了n个古代词语。大门闪烁的古代文字其实是一篇文章,文章由m个段落构成,每个段落都是1个古代词语。你需要做的是记录这篇文章,在文章中找出连续的一些段落,其中包含最多的出现的石碑上的古代词语(重复的只算一个)。并且在石碑上出现的古代词语数量尽量多的情况下,还要使选出的文章段落尽量短,最终得到两个数字输出石碑,即可打开大门。

输入格式:

第 1 行一个数 n,接下来 n 行每行是一个长度不超过 10 的字符串,表示一个石碑上出现的古代词语。

接着是一个数 m,然后是 m 行长度不超过 10 的字符串,每个表示文章中的一个段落。

输出格式:

输出文件共 2 行。第 1 行为文章中最多包含的石碑上的古代词语,第 2 行表示在文章中包含最多石碑上出现的最短的连续段的长度。

样例1输入:

3 wink cat art 5 wink cat cat art wink

样例1输出:

3 3

样例2输入:

5 aa bb cc dd aa 6 aa z cc cc bb cc

样例2输出:

3 5

数据规模:

对于 100% 的数据,n≤1000,m≤10^5。

样例2解释:

aa,bb,cc都在文章中出现过,所以第一问答案是3

最短的区间是[1,4],也就是aa,cc,cc,bb,包含aa,bb,cc,所以长度是4-1+1=4

unordered_set<string> se;
7
    for (int i = 0; i < n; i++) {
8
        string s;
9
        cin >> s;
10
        se.insert(s);
11
    }
12
    cin >> m;
13
    vector<string> article(m);
14
    for (int i = 0; i < m; i++) {
15
        cin >> article[i];
16
    }
17
    int left = 0, right = 0, count = 0, minLen = m + 1, maxCount = 0;
18
    unordered_map<string, int> window;
19
    while (right < m) {
20
        string s = article[right];
21
        right++;
22
        if (se.count(s)) {
23
            window[s]++;
24
            if (window[s] == 1) count++;
25
        }
26
        while (count == se.size()) {
27
            if (right - left < minLen) {
28
                minLen = right - left;
29
                maxCount = count;
30
            }
31
            string s = article[left];
32
            left++;
33
            if (se.count(s)) {
34
                window[s]--;
35
                if (window[s] == 0) count--;
36
            }
37
        }
38
    }
39
    cout << maxCount << endl << minLen << endl;
2 个赞

《重要代码只有两行》

3 个赞