1. 程式人生 > 其它 >P1204 [USACO1.2]擠牛奶Milking Cows 線段樹優化

P1204 [USACO1.2]擠牛奶Milking Cows 線段樹優化

P1204 [USACO1.2]擠牛奶Milking Cows
從暴力思想出發,建立一個bool陣列用來標記哪些時間有擠牛奶,哪些時間空閒,然後從有擠牛奶的時間開始統計每一個段擠牛奶時間和空閒時間,並求最長擠牛奶時間和最長空閒時間,這樣做時間複雜度為O(n*s),s為擠牛奶的時間長度,會TLE。如果優化呢?對於擠牛奶時間可以看成區間更新,然後統計每個時間點有多少人擠牛奶,可看成單點查詢,故可以使用線段樹進行優化時間複雜度O(nlogs)。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
int t[maxn<<2];
int b[maxn];
void build(int rt,int l,int r)
{
	if (l==r) return ;
	int mid=(l+r)>>1;
	build(2*rt,l,mid);
	build(2*rt+1,mid+1,r);
} 
void update(int rt,int l,int r,int ql,int qr,int k)
{
	if (ql<=l&&r<=qr)
	{
		t[rt]=k;
	}
	else
	{
		int mid=(l+r)>>1;
		if (ql<=mid) update(rt*2,l,mid,ql,qr,k);
		if (qr>mid) update(rt*2+1,mid+1,r,ql,qr,k);
	}
}
int getsum(int rt,int l,int r,int x)
{
	if (l==r)
	{
		return t[rt];
	}
	else
	{
		int mid=(l+r)>>1;
		if (x<=mid) return t[rt]+getsum(rt*2,l,mid,x);
		else return t[rt]+getsum(2*rt+1,mid+1,r,x);
	}
}
int main()
{
	ios::sync_with_stdio(false);
	int lmin=1e6,rmax=0;
	int n;
	cin>>n;
	build(1,0,1e6);
	for (int i=1;i<=n;i++)
	{
		int x,y;
		cin>>x>>y;
		lmin=min(lmin,x);rmax=max(rmax,y);
		update(1,0,1e6,x,y-1,1);
	}
	for (int i=lmin;i<=rmax;i++) 
	{
		b[i]=getsum(1,0,1e6,i);	
	}
	int ans1=0,ans2=0,c1=0,c2=0;
	for (int i=lmin;i<=rmax;i++)
	{
		if (b[i]==0)
		{
			ans1=max(ans1,c2);
			c1++;
			c2=0;
		}
		else
		{
			ans2=max(ans2,c1);
			c2++;
			c1=0;
		}
	}
	cout<<ans1<<" "<<ans2<<endl;
	return 0;
}
/*
3
300 1000
700 1200
1500 2100

*/