題解 洛谷P2161 會場預約(線段樹)

2021-08-21 21:48:00 字數 1564 閱讀 8961

先說一下這道題的解題思路,我們使用離線操作的做法。記錄讀入的資料,把開始結束日期存在結構體裡,並記錄是a操作還是b操作。開乙個陣列記錄染色情況、乙個cnt陣列記錄第幾個操作推掉了幾個預約,讀入後我們倒著迴圈進行查詢,如果讀入的是b就跳過,如果是a的話就將開始到結束日期的所有點染成當前序號的顏色。如果迴圈到某段日期它已經有染色標記了,就將當前那段日期所對應的的染色標記的最小值的推掉的預約數+1(因為是倒著來的)(較小的那個標記:明明是我先來的)。最後正著輸出答案,如果是a操作就輸出當前的cnt,在主函式開乙個變數ans記錄b操作的答案,並且a操作結束後ans要加上1減去cnt[i](新增了1個預約,推掉了cnt[i]個預約)。

顯然 資料範圍拒絕我們用暴力的方法解決染色和查詢最小值的操作,所以我們只能用線段樹。線段樹的範圍為1到100000,開乙個陣列minn記錄某個結點的minn值,初始化為最大值1e9。先寫下放標記和最小值的函式,如果父親結點的標記為0就不下放,否則就用父親節點的標記覆蓋孩子節點的標記和最小值,父親節點標記清零。然後是染色的函式,這裡在染色的過程中注意更新最小值。再是查詢區間最小值的函式,線段樹寫過

#include#include#include#define ll long long 

using namespace std;

const int maxn=200010;

int mark[maxn*8];

int n;

int ans=0;

struct borrow

a[maxn];

int b[maxn];

int cnt[maxn];

int minn[maxn*8];

void pushdown(int now,int l,int r)

ll getminn(int now,int l,int r,int x,int y)

int mid=(l+r)/2;

ll ans=1e9;

if(x<=mid) ans=min(ans,getminn(now*2,l,mid,x,y));

if(mid+1<=y) ans=min(ans,getminn(now*2+1,mid+1,r,x,y));

return ans;

}void addnum(int now,int l,int r,int x,int y,int k)

if(mark[now]==k)

int mid=(l+r)/2;

if(x<=mid) addnum(now*2,l,mid,x,y,k);

if(mid+1<=y) addnum(now*2+1,mid+1,r,x,y,k);

minn[now]=min(minn[now*2],minn[now*2+1]);

}int main()

for(int i=1;i<=n;i++)

if(c=='b')

}for(int i=n;i>=1;i--)

addnum(1,1,100000,a[i].x,a[i].y,i);

} }for(int i=1;i<=n;i++)

else

}return 0;

}

洛谷2161 會場預約 題解

好吧,用stl水過了一道題。顯然,每一次進行修改之前的所有預約一定是沒有互相覆蓋的。我們用set保留所有的預約,這樣在詢問時只要輸出set的size就行了 對於每次的新預約,我們就先找到右端點大於該區間左端端點的區間,然後乙個乙個刪除矛盾的預約就行了 複雜度大概為o n logn 2 bzoj上這道...

P2161 會場預約 區間染色

這題可以轉換成區間染色的問題,即對一段區間進行染色,問最後純色的區間一共有多少個 不超過一種顏色的區間 對每一段區間維護乙個color和tag,color 0代表該區間染了一種顏色,color 1代表區間雜色,color 0代表區間無色。tag就是乙個懶惰標記。這裡有兩個操作 查詢當前 l,r 染色...

樹狀陣列 二分 洛谷 P2161 會場預約

pp大廈有一間空的禮堂,可以為企業或者單位提供會議場地。這些會議中的大多數都需要連續幾天的時間 個別的可能只需要一天 不過場地只有乙個,所以不同的會議的時間申請不能夠衝突。也就是說,前乙個會議的結束日期必須在後乙個會議的開始日期之前。所以,如果要接受乙個新的場地預約申請,就必須拒絕掉與這個申請相衝突...