刷漆 (分块 差分 及其他)

题目描述

小J被安排一个艰巨的任务:给n面墙刷漆,n面墙是连在一起的。按照要求她要进行m个次工作,每次对[a,b]这个区间的墙刷一次漆。她想知道,她完成工作之后,每面墙被刷了多少次漆。编个程序算算吧。。

输入

第一行两个整数n和m

接下m行,每行两个整数a和b,表示小J要对[a,b]这个区间的墙进行刷漆。

输出

输出n个整数,表示每面墙被刷了多少次漆。

这道题比较考验yy能力,一般人都会先想到将刷漆的起始点和终点开两个数组存起来,然后最后再一遍扫过去,遇到开头就+1,遇到结尾就-1,小C说这种方法叫“差分”,听起来很高大上的样子。


代码:

#include<bits/stdc++.h>
using namespace std;
struct node{
    int q;
    int h;
};
node A[100005];
int cnt1[100005];
int cnt2[100005];
int ans=0;
int main(){
    int n,m;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&A[i].q,&A[i].h);
        cnt1[A[i].q]++;
        cnt2[A[i].h]++;
    }
    for(int i=1;i<=n;i++){
        ans=ans+cnt1[i];
        printf("%d ",ans);
        ans=ans-cnt2[i];
    }
    return 0;
}


然而还有其他的方法,“分块”。

小C说,可以举这样一个例子,学校里对于一定学号区间内的人要发作业,那么可以先将包含在一个班级中的人的作业交给他们的班主任,及维护一个整体。


代码如下:

#include<bits/stdc++.h>//刷漆 分块 
using namespace std;
int n,m,a,b,len,bzr[400],cnt[100005];
int main(){
    cin>>n>>m;len=sqrt(n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&a,&b);
        for(int j=a-1;j<=b-1;)
            if(j%len==0&&j+len<=b)bzr[j/len]++,j+=len;
            else cnt[j++]++;
    }
    for(int i=0;i<n;i++)
        printf("%d ",cnt[i]+bzr[i/len]);
    return 0;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章