BZOJ1577: [Usaco2009 Feb]庙会捷运Fair Shuttle
n<=20000个车站,车能同时载C<=100个人,求能满足K<=50000群人的多少个。每群人给起点终点和人数,一群人不一定要都满足。
一开始想DP,想不出,很菜。
贪心即可。如果有右端点相同的几群人,那肯定优先满足左端点大的;如果有两群人发生冲突,而我们从左到右考虑区间的话,那肯定让左边的人先满足,因为他对后面的人影响小。所以先排个序然后模拟即可。模拟用线段树。
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 using namespace std; 7 8 int n,K,C; 9 #define maxn 50011 10 struct SMT 11 { 12 struct Node 13 { 14 int Min; 15 int add; 16 int l,r; 17 int ls,rs; 18 }a[maxn]; 19 int size; 20 SMT() {size=0;} 21 void build(int &x,int L,int R) 22 { 23 x=++size; 24 a[x].Min=C; 25 a[x].add=0; 26 a[x].l=L;a[x].r=R; 27 if (L==R) {a[x].ls=a[x].rs=0;return;} 28 const int mid=(L+R)>>1; 29 build(a[x].ls,L,mid); 30 build(a[x].rs,mid+1,R); 31 } 32 void build() {int x;build(x,1,n);} 33 void up(int x) 34 { 35 const int &p=a[x].ls,&q=a[x].rs; 36 a[x].Min=min(a[p].Min,a[q].Min); 37 } 38 void add_single(int x,int v) 39 { 40 a[x].Min+=v; 41 a[x].add+=v; 42 } 43 void down(int x) 44 { 45 const int &p=a[x].ls,&q=a[x].rs; 46 if (a[x].add) 47 { 48 add_single(p,a[x].add); 49 add_single(q,a[x].add); 50 a[x].add=0; 51 } 52 } 53 int ql,qr,v; 54 void Add(int x) 55 { 56 if (ql<=a[x].l && a[x].r<=qr) add_single(x,v); 57 else 58 { 59 down(x); 60 const int mid=(a[x].l+a[x].r)>>1; 61 if (ql<=mid) Add(a[x].ls); 62 if (qr>mid) Add(a[x].rs); 63 up(x); 64 } 65 } 66 void Add(int l,int r,int v) 67 { 68 this->ql=l,this->qr=r,this->v=v; 69 Add(1); 70 } 71 int qmin(int x) 72 { 73 if (ql<=a[x].l && a[x].r<=qr) return a[x].Min; 74 else 75 { 76 down(x); 77 const int mid=(a[x].l+a[x].r)>>1; 78 int ans=C; 79 if (ql<=mid) ans=min(ans,qmin(a[x].ls)); 80 if (qr>mid) ans=min(ans,qmin(a[x].rs)); 81 return ans; 82 } 83 } 84 int qmin(int l,int r) 85 { 86 this->ql=l,this->qr=r; 87 return qmin(1); 88 } 89 }t; 90 struct segment 91 { 92 int l,r,v; 93 bool operator < (const segment &b) const 94 {return r<b.r || (r==b.r && l>b.l);} 95 }s[maxn]; 96 int main() 97 { 98 scanf("%d%d%d",&K,&n,&C); 99 t.build(); 100 for (int i=1;i<=K;i++) scanf("%d%d%d",&s[i].l,&s[i].r,&s[i].v); 101 sort(s+1,s+1+K); 102 int ans=0; 103 for (int i=1;i<=K;i++) 104 { 105 int tmp=min(t.qmin(s[i].l,s[i].r-1),s[i].v); 106 ans+=tmp; if (tmp) t.Add(s[i].l,s[i].r-1,-tmp); 107 } 108 printf("%d\n",ans); 109 return 0; 110 }