題目描述
小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;
}