洛谷P3028 [USACO10OCT]汽水機Soda Machine
阿新 • • 發佈:2018-11-25
題意翻譯
為了滿足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; }