洛谷 1937 [USACO10MAR]仓配置Barn Allocation
【题解】
贪心。 把区间按照右端点从小到大排序,右端点相同的按照长度从小到大排序,然后按顺序考虑,能放就放下去。 维护能不能放下去用线段树即可。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define LL long long 5 #define rg register 6 #define N 100010 7 #define ls (u<<1) 8 #define rs (u<<1|1) 9 using namespace std; 10 int n,m,ans,mn[N<<2],del[N<<2]; 11 struct seg{ 12 int l,r; 13 }a[N]; 14 inline int read(){ 15 int k=0,f=1; char c=getchar(); 16 while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar(); 17 while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar(); 18 return k*f; 19 } 20 void build(int u,int l,int r){ 21 if(l<r){ 22 int mid=(l+r)>>1; 23 build(ls,l,mid),build(rs,mid+1,r),mn[u]=min(mn[ls],mn[rs]); 24 } 25 else mn[u]=read(); 26 } 27 inline void pushdown(int u){ 28 mn[ls]+=del[u]; del[ls]+=del[u]; 29 mn[rs]+=del[u]; del[rs]+=del[u]; 30 del[u]=0; 31 } 32 void update(int u,int l,int r,int ul,int ur){ 33 if(ul<=l&&r<=ur){ 34 mn[u]--; del[u]-=1; 35 return; 36 } 37 int mid=(l+r)>>1; pushdown(u); 38 if(ul<=mid) update(ls,l,mid,ul,ur); 39 if(ur>mid) update(rs,mid+1,r,ul,ur); 40 mn[u]=min(mn[ls],mn[rs]); 41 } 42 int query(int u,int l,int r,int ul,int ur){ 43 if(ul<=l&&r<=ur) return mn[u]; 44 int mid=(l+r)>>1,ret=2e9; pushdown(u); 45 if(ul<=mid) ret=min(ret,query(ls,l,mid,ul,ur)); 46 if(ur>mid) ret=min(ret,query(rs,mid+1,r,ul,ur)); 47 return ret; 48 } 49 inline bool cmp(seg a,seg b){ 50 if(a.r==b.r) return a.l>b.l; 51 return a.r<b.r; 52 } 53 int main(){ 54 n=read(); m=read(); build(1,1,n); 55 for(rg int i=1;i<=m;i++) a[i].l=read(),a[i].r=read(); 56 sort(a+1,a+1+m,cmp); 57 for(rg int i=1;i<=m;i++){ 58 int tmp=query(1,1,n,a[i].l,a[i].r); 59 if(tmp>0){ 60 ans++; 61 update(1,1,n,a[i].l,a[i].r); 62 } 63 } 64 printf("%d\n",ans); 65 return 0; 66 }