首页 > 代码库 > BZOJ3389: [Usaco2004 Dec]Cleaning Shifts安排值班

BZOJ3389: [Usaco2004 Dec]Cleaning Shifts安排值班

3389: [Usaco2004 Dec]Cleaning Shifts安排值班

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 45  Solved: 26
[Submit][Status]

Description

    一天有T(1≤T≤10^6)个时段.约翰正打算安排他的N(1≤N≤25000)只奶牛来值班,打扫
打扫牛棚卫生.每只奶牛都有自己的空闲时间段[Si,Ei](1≤Si≤Ei≤T),只能把空闲的奶牛安排出来值班.而且,每个时间段必需有奶牛在值班.  那么,最少需要动用多少奶牛参与值班呢?如果没有办法安排出合理的方案,就输出-1.

Input

 
    第1行:N,T.
    第2到N+1行:Si,Ei.

Output

 
    最少安排的奶牛数.

Sample Input


3 10
1 7
3 6
6 10

Sample Output


2


样例说明
奶牛1和奶牛3参与值班即可.

HINT

 

Source

Silver

题解:
此题<清理牛棚  线段树而已
代码:
 1  #include<cstdio> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<algorithm> 6 #include<iostream> 7 #include<vector> 8 #include<map> 9 #include<set>10 #include<queue>11 #include<string>12 #define inf 100000000013 #define maxn 1000000+1000014 #define maxm 500+10015 #define eps 1e-1016 #define ll long long17 #define pa pair<int,int>18 #define for0(i,n) for(int i=0;i<=(n);i++)19 #define for1(i,n) for(int i=1;i<=(n);i++)20 #define for2(i,x,y) for(int i=(x);i<=(y);i++)21 #define for3(i,x,y) for(int i=(x);i>=(y);i--)22 #define mod 100000000723 using namespace std;24 inline int read()25 {26     int x=0,f=1;char ch=getchar();27     while(ch<0||ch>9){if(ch==-)f=-1;ch=getchar();}28     while(ch>=0&&ch<=9){x=10*x+ch-0;ch=getchar();}29     return x*f;30 }31 struct rec{int l,r;}a[maxn];32 struct seg{int l,r,mi,tag;}t[4*maxn];33 int n,m;34 inline bool cmp(rec a,rec b)35 {36     return a.l<b.l||(a.l==b.l&&a.r<b.r);37 }38 inline void pushup(int k)39 {40     t[k].mi=min(t[k<<1].mi,t[k<<1|1].mi);41 }42 inline void update(int k,int z)43 {44     t[k].mi=min(t[k].mi,z);45     t[k].tag=min(t[k].tag,z);46 }47 inline void pushdown(int k)48 {49     if(t[k].tag==inf)return ;50     update(k<<1,t[k].tag);51     update(k<<1|1,t[k].tag);52     t[k].tag=inf;53 }54 inline void build(int k,int x,int y)55 {56     int l=t[k].l=x,r=t[k].r=y,mid=(l+r)>>1;t[k].tag=inf;57     if(l==r){t[k].mi=l==0?0:inf;return ;}58     build(k<<1,l,mid);build(k<<1|1,mid+1,r);59     pushup(k);60 }61 inline ll query(int k,int x)62 {63     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;64     if(l==r)return t[k].mi;65     pushdown(k);66     if(x<=mid)return query(k<<1,x);else return query(k<<1|1,x);67 }68 inline void change(int k,int x,int y,int z)69 {70     int l=t[k].l,r=t[k].r,mid=(l+r)>>1;71     if(l==x&&r==y){update(k,z);return;}72     pushdown(k);73     if(y<=mid)change(k<<1,x,y,z);74     else if(x>mid)change(k<<1|1,x,y,z);75     else change(k<<1,x,mid,z),change(k<<1|1,mid+1,y,z);76     pushup(k);77 }78 int main()79 {80     freopen("input.txt","r",stdin);81     freopen("output.txt","w",stdout);82     n=read();m=read();83     for1(i,n)a[i].l=read(),a[i].r=read();84     sort(a+1,a+n+1,cmp);85     build(1,0,m);86     for1(i,n)87     {88         ll t=query(1,a[i].l-1);89         if(t!=inf)change(1,a[i].l,a[i].r,t+1);else break;90     }91     ll ans=query(1,m);92     printf("%lld\n",ans==inf?-1:ans);93     return 0;94 }
View Code

 差了题解发现居然还有贪心做法:

iwtwiioi:

显然左端点排序后,依次取。

要考虑下一次取的方案:

待选点为a[j].x<=a[now].y+1的所有点j,其中now是当前所选

那么我们要在这些点内做决策

贪心就是取y最大的待选点,即

max(a[j].y)的j

orzzzzzzzzzz

代码:(copy)

 1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <string> 5 #include <iostream> 6 #include <algorithm> 7 #include <queue> 8 using namespace std; 9 #define rep(i, n) for(int i=0; i<(n); ++i)10 #define for1(i,a,n) for(int i=(a);i<=(n);++i)11 #define for2(i,a,n) for(int i=(a);i<(n);++i)12 #define for3(i,a,n) for(int i=(a);i>=(n);--i)13 #define for4(i,a,n) for(int i=(a);i>(n);--i)14 #define CC(i,a) memset(i,a,sizeof(i))15 #define read(a) a=getint()16 #define print(a) printf("%d", a)17 #define dbg(x) cout << #x << " = " << x << endl18 #define printarr2(a, b, c) for1(i, 1, b) { for1(j, 1, c) cout << a[i][j]; cout << endl; }19 #define printarr1(a, b) for1(i, 1, b) cout << a[i]; cout << endl20 inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<0||c>9; c=getchar()) if(c==-) k=-1; for(; c>=0&&c<=9; c=getchar()) r=r*10+c-0; return k*r; }21 inline const int max(const int &a, const int &b) { return a>b?a:b; }22 inline const int min(const int &a, const int &b) { return a<b?a:b; }23  24 const int N=25005;25 int n, t, cnt;26 struct dat { int x, y; }a[N];27 bool cmp(const dat &a, const dat &b) { return a.x==b.x?a.y<b.y:a.x<b.x; }28  29 int main() {30     read(n); read(t);31     for1(i, 1, n) read(a[i].x), read(a[i].y);32     sort(a+1, a+1+n, cmp);33     a[n+1].x=100055050;34     for1(i, 1, n) if(a[i].x!=a[i+1].x) a[++cnt]=a[i];35     if(a[1].x>1) { puts("-1"); return 0; }36     int ans=1, now=1;37     for1(i, 1, cnt) {38         int fix=0, nx=now, pos=0, ed=a[now].y;39         while(nx<cnt && a[nx+1].x<=ed+1) {40             ++nx;41             if(a[nx].y>ed && fix<a[nx].y) {42                 fix=a[nx].y;43                 pos=nx;44             }45         }46         if(a[now].y==t) break;47         if(nx==now || fix==0) { puts("-1"); return 0; }48         now=pos;49         i=nx;50         ++ans;51     }52     if(a[now].y!=t) puts("-1");53     else print(ans);54     return 0;55 }
View Code

 

BZOJ3389: [Usaco2004 Dec]Cleaning Shifts安排值班