UVALive 6606 Meeting Room Arrangement
COJ有这题,一模一样的,COJ应该是从这个OJ上拿的吧。
按右端点排序,然后从第一个开始贪心的取相邻的。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<bitset> #define mem(a,b) memset(a,b,sizeof(a)) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define llson j<<1,l,mid #define rrson j<<1|1,mid+1,r #define INF 0x7fffffff #define maxn 40 using namespace std; typedef long long ll; typedef unsigned long long ull; struct abc { int l,r; bool operator<(const abc &b)const { return r<b.r; } }a[22]; int main() { //freopen("1.txt","r",stdin); int n; scanf("%d",&n); while(n--) { int i,j,l,r,sum=1; for(i=0;;i++) { scanf("%d%d",&l,&r); if(l==0&&r==0) break; a[i].l=l,a[i].r=r; } sort(a,a+i); l=a[0].r; for(j=1;j<i;j++) if(a[j].l>=l) sum++,l=a[j].r; printf("%d\n",sum); } return 0; }
思路:RMQ+二分
把递推和用RMQ先预处理一下区间最大值,然后枚举下标 i,然后二分查找 i 后面>=x位置的最小值,其差就是区间。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<bitset> #define mem(a,b) memset(a,b,sizeof(a)) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define llson j<<1,l,mid #define rrson j<<1|1,mid+1,r #define INF 0x7fffffff #define maxn 500050 using namespace std; typedef long long ll; typedef unsigned long long ull; ll a[maxn],dp[maxn][34]; void RMQ(int n) { int i,j; for(i=1;i<=n;i++) dp[i][0]=a[i]; for(j=1;(1<<j)<=n;j++) for(i=1;i+(1<<j)-1<=n;i++) dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]); } ll rmq(int l,int r) { int k=log2(r-l+1.0); return max(dp[l][k],dp[r-(1<<k)+1][k]); } int main() { //freopen("1.txt","r",stdin); int t; scanf("%d",&t); while(t--) { int n,x,i,ans; scanf("%d%d",&n,&x); for(i=1;i<=n;i++) scanf("%lld",a+i),a[i]=a[i]+a[i-1]; RMQ(n); for(i=0,ans=INF;i<n;i++) { int l=i+1,r=n,mid; while(l<r) { mid=(l+r)>>1; if(rmq(i+1,mid)-a[i]>=x) r=mid; else l=mid+1; } if(a[r]-a[i]>=x) ans=min(ans,r-i); } if(ans==INF) puts("-1"); else printf("%d\n",ans); } return 0; }
UVALive 6604 Airport Sort
思路:由k对数进行分组,然后用归并求出最小的交换次数。然后先求出第二种的最大的移动时间。它们之差就是答案。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<map> #include<queue> #include<set> #include<cmath> #include<bitset> #define mem(a,b) memset(a,b,sizeof(a)) #define lson i<<1,l,mid #define rson i<<1|1,mid+1,r #define llson j<<1,l,mid #define rrson j<<1|1,mid+1,r #define INF 0x7fffffffffffffff #define maxn 20050 using namespace std; typedef long long ll; typedef unsigned long long ull; ll sum; void merge(ll A[], int p, int q, int r) { int n1 = q - p + 1; int n2 = r - q; ll *L=new ll[n1 + 1]; ll *R=new ll[n2 + 1]; for(int i = 0; i < n1; i++) L[i] = A[p + i]; for(int i = 0; i < n2; i++) R[i] = A[q + 1 + i]; L[n1] = INF; R[n2] = INF; int i = 0, j = 0; for(int k = p; k <= r; k++) { if(L[i] <= R[j]) A[k] = L[i],i++; else A[k] = R[j],j++,sum += n1 - i; } delete []L; delete []R; } void mergesort(ll A[], int l, int r) { if(l >= r) return ; int q = (l + r) / 2; mergesort(A, l, q); mergesort(A, q + 1, r); merge(A, l, q, r); } ll a[maxn]; int main() { //freopen("1.txt","r",stdin); int t,ii=1; scanf("%d",&t); while(t--) { int n,k,i; ll ans=0;sum=0; scanf("%d%d",&n,&k); for(i=1;i<=n;i++) { scanf("%d",a+i),a[i]=(a[i]-1)/k+1; int mm=(i-1)/k+1; if(mm>a[i]) ans=max(ans,i-k*a[i]); else if(mm<a[i]) ans=max(ans,k*(a[i]-1)-i+1); } mergesort(a,1,n); printf("Case %d: %lld\n",ii++,sum-ans); } return 0; }