刷漆 (分塊 差分 及其他)

題目描述

小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;
}


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