1. 程式人生 > >P1047 校門外的樹

P1047 校門外的樹

amp 表示 turn 端點 前綴 spa 代碼 進行 情況

題目描述

某校大門外長度為L的馬路上有一排樹,每兩棵相鄰的樹之間的間隔都是1米。我們可以把馬路看成一個數軸,馬路的一端在數軸0的位置,另一端在L的位置;數軸上的每個整數點,即0,1,2,……,L,都種有一棵樹。

由於馬路上有一些區域要用來建地鐵。這些區域用它們在數軸上的起始點和終止點表示。已知任一區域的起始點和終止點的坐標都是整數,區域之間可能有重合的部分。現在要把這些區域中的樹(包括區域端點處的兩棵樹)移走。你的任務是計算將這些樹都移走後,馬路上還有多少棵樹。

輸入輸出格式

輸入格式:

輸入文件tree.in的第一行有兩個整數L(1 <= L <= 10000)和 M(1 <= M <= 100),L代表馬路的長度,M代表區域的數目,L和M之間用一個空格隔開。接下來的M行每行包含兩個不同的整數,用一個空格隔開,表示一個區域的起始點和終止點的坐標。

輸出格式:

輸出文件tree.out包括一行,這一行只包含一個整數,表示馬路上剩余的樹的數目。

輸入輸出樣例

輸入樣例#1: 復制
500 3
150 300
100 200
470 471
輸出樣例#1: 復制
298

說明

NOIP2005普及組第二題

對於20%的數據,區域之間沒有重合的部分;

對於其它的數據,區域之間有重合的情況。

PJ第二題,可以說是非常水。

我們可以用最簡單的模擬,即vis為是否有數,然後暴力……

高級一點,用STL的set記錄移除的樹,然後用l+1-set.size()就是答案。

還可以用差分,每次[l,r]就立刻使a[l]++,a[r+1]--,然後判斷a[i]是否大於0,等於0則沒有移除。

當然差分的前綴和不難想到樹狀數組……

還有方法!!

可以用線段樹進行區間修改……看代碼吧。

AC代碼如下:

#include<cstdio>
#include<algorithm>
using namespace std;
const int N=10000+5;
int sum[N<<2],L,R,m,n;
void init(int now,int l,int r)
{
    if(l==r) sum[now]=1;
    else {
        int mid=(l+r)>>1;
        init(now<<1,l,mid);
        init(now
<<1|1,mid+1,r); sum[now]=sum[now<<1]+sum[now<<1|1]; } return; } void update(int now,int l,int r,int ql,int qr) { if(!sum[now]) return; if(ql<=l&&r<=qr) {sum[now]=0;return;} int mid=(l+r)>>1; if(mid>=ql) update(now<<1,l,mid,ql,qr); if(qr>mid) update(now<<1|1,mid+1,r,ql,qr); sum[now]=sum[now<<1]+sum[now<<1|1]; return; } int main() { scanf("%d%d",&m,&n); init(1,1,m+1); for(int i=1;i<=n;i++) scanf("%d%d",&L,&R),update(1,1,m+1,L+1,R+1); printf("%d",sum[1]); return 0; }

P1047 校門外的樹