1. 程式人生 > >洛谷P3028 [USACO10OCT]汽水機Soda Machine

洛谷P3028 [USACO10OCT]汽水機Soda Machine

題意翻譯

為了滿足fj所有的N(1<=n<=50000)頭奶牛的需求,fj新買了一臺汽水機。他想找到一個最完美的位置來安放它。

奶牛的牧場可以被表示為一個一維數軸,第i個奶牛被放牧的區間是[Ai...Bi](包含端點),fj可以把汽水機放在[1..1,000,000,000]。

因為奶牛們都懶得要死,她們想盡可能的少移動。她們希望汽水機被放在自己的放牧區間內。

遺憾的是,fj並不總能滿足所有奶牛的要求,所以他想請你幫忙算出他能滿足的奶牛數目

 

輸入

4 
3 5 
4 8 
1 2 
5 10 

輸出

3

 

根據觀察,可以發現區間都非常大達到10^9如果直接暴力是O(10^9n)肯定會超時,所以我採用了離散化,將區間離散

這樣可以把最大時間複雜度降低到O(n^2)

程式碼:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
inline int read(){
	int x=0,f=0;char s=getchar();
	while(!isdigit(s))f|=s=='-',s=getchar();
	while( isdigit(s))x=(x<<1)+(x<<3)+s-48,s=getchar();
	return f==0?x:-x;
}
const int N=5e4+10;
struct LSnode{
	int x,z,p;
	inline bool operator<(const LSnode &k)const{
		return x<k.x;
	}
}b[N<<1];int a[N<<1];
int n;
int sum[N<<1];
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		b[2*i-1].x=read();
		b[2*i  ].x=read();
		b[2*i-1].p=2*i-1;
		b[2*i  ].p=2*i;
	}
	sort(b+1,b+2*n+1);
	b[1].z=1;
	for(int i=2;i<=(n<<1);i++){
		if(b[i].x==b[i-1].x)b[i].z=b[i-1].z;
		else b[i].z=b[i-1].z+1;
	}
	for(int i=1;i<=(n<<1);i++)a[b[i].p]=b[i].z;
	int maxx=0;
	for(int i=1;i<=n;i++){
		for(int j=a[2*i-1];j<=a[2*i];j++)
			sum[j]++,maxx=max(maxx,sum[j]);
	}
	printf("%d\n",maxx);
	return 0;
}

但是這個時間複雜度是O(n^2)還是會超時兩個點,所以我想可以在區間修改時優化一下

因為上面的程式碼每次修改都是要從左到右每一個點都+1,所以我們可以考慮用字首和的方式優化,因此只需要在每個區間的其實點+1,在區間的結束點+1的位置上-1,統計時不斷的加這個點的sum值就好了

AC程式碼

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
inline int read(){
	int x=0,f=0;char s=getchar();
	while(!isdigit(s))f|=s=='-',s=getchar();
	while( isdigit(s))x=(x<<1)+(x<<3)+s-48,s=getchar();
	return f==0?x:-x;
}
const int N=5e4+10;
struct LSnode{
	int x,z,p;
	inline bool operator<(const LSnode &k)const{
		return x<k.x;
	}
}b[N<<1];int a[N<<1];
int n;
int sum[N<<1];
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		b[2*i-1].x=read();
		b[2*i  ].x=read();
		b[2*i-1].p=2*i-1;
		b[2*i  ].p=2*i;
	}
	sort(b+1,b+2*n+1);
	b[1].z=1;
	for(int i=2;i<=(n<<1);i++){
		if(b[i].x==b[i-1].x)b[i].z=b[i-1].z;
		else b[i].z=b[i-1].z+1;
	}
	for(int i=1;i<=(n<<1);i++)a[b[i].p]=b[i].z;
	int maxx=0;
	for(int i=1;i<=n;i++){
		sum[a[2*i-1]]++;
		sum[a[2*i]+1]--;
	}
	int s=0;
	for(int i=1;i<=b[n<<1].z;i++)s+=sum[i],maxx=max(maxx,s);
	printf("%d\n",maxx);
	return 0;
}