USACO 2018 US Open Contest, Gold

Out of Sorts(bzoj5278)

题意
双向冒泡排序,问如下程序中 “moo” 会出现几次
图片标题
代码

#include <cstdio>
#include <algorithm>
using namespace std;
#define N 100010
int n,ans=0,tree[N];
struct node{int x,id;}a[N];
bool cmp(node x,node y){
    return x.x<y.x || (x.x==y.x && x.id<y.id);
}
inline void add(int x){
    for(;x<=n;x+=x&(-x)) tree[x]++;
}
inline int query(int x){
    int y=0;
    for(;x;x-=x&(-x)) y+=tree[x];
    return y;
}
int main(){
    freopen("a.in","r",stdin);
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].id=i;
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;i++){
        add(a[i].id);
        ans=max(ans,i-query(i));
    }
    printf("%d\n",max(1,ans));
    return 0;
}

Milking Order(bzoj5280)

题意

n n 个点 m 个条件,每个条件表示其中一些数按顺序排列
找最大的 x x ,使得前 x 个条件同时成立的排列顺序,若有多个可能顺序,取字典序最小的

题解

首先处理x,可以二分求出x的最大值(拓扑判可不可行)
对于前x个条件,建图,优先队列维护得到字典序最小的解

代码

#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define N 100010
#define ll long long
#define inf 0x3f3f3f3f
int n,m,num=0,cnt=0,len[N],st[N],ed[N],in[N],h[N],a[N<<1];
struct node{int x,y,next;}mp[N<<1];
inline void insert(int x,int y){
    mp[++cnt].x=x;mp[cnt].y=y;mp[cnt].next=h[x];h[x]=cnt;
    in[y]++;
}
inline void build(int x){
    cnt=0;memset(in,0,sizeof(in));
    memset(h,0,sizeof(h));
    for(int i=1;i<=x;i++){
        for(int j=st[i];j<ed[i];j++){
            insert(a[j],a[j+1]);
        }
    }
}
inline bool check(int x){
    build(x);
    queue<int>q;
    int ans=0;
    for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
    while(!q.empty()){
        int x=q.front();q.pop();ans++;
        for(int i=h[x];i;i=mp[i].next){
            in[mp[i].y]--;
            if(!in[mp[i].y]) q.push(mp[i].y);
        }
    }
    if(ans==n) return 1;
    return 0;
}
inline void findans(int x){
    build(x);
    priority_queue<int,vector<int>, greater<int> > q; 
    for(int i=1;i<=n;i++) if(!in[i]) q.push(i);
    while(!q.empty()){
        int x=q.top();q.pop();printf("%d ",x);
        for(int i=h[x];i;i=mp[i].next){
            in[mp[i].y]--;
            if(!in[mp[i].y]) q.push(mp[i].y);
        }
    }
}

int main(){
    freopen("milkorder.in","r",stdin);
//  freopen("milkorder.out","w",stdout);
    scanf("%d%d",&n,&m);
    for(int i=1;i<=m;i++){
        scanf("%d",&len[i]);
        st[i]=num+1;
        for(int j=1;j<=len[i];j++) scanf("%d",&a[++num]);
        ed[i]=num;
    }
    int l=1,r=m,ans=0;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    findans(ans);
    return 0;
}

Talent Show(bzoj5281)

题意

n n 头牛,每头牛有一个体重值 wi 和才艺值 ti t i
在其中选择任意头牛,在满足体重值大于 m m 的情况下,问 tw 的最大值

题解
显然贪心是不成立的
假设 tw=x ∑ t ∑ w = x ,其中 x x 为最大值
那么就有 t1xw1+t2+xw2+tkxwk=0
因此我们可以去二分这个 x x ,然后 dp 找可不可能出现值大于0的
若出现大于0的,就说明这个x不是最大值,还要更大的..

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 1010
#define ll long long
#define inf 0x3f3f3f3f
int ans=0,n,m,w[260],t[260];
ll f[N]; 
inline bool check(int x){
    for(int i=1;i<=m;i++) f[i]=-inf;f[0]=0;
    for(int i=1;i<=n;i++){
        for(int j=m;j>=0;j--){
            if(f[j]==-inf) continue;
            int k=min(m,j+w[i]);
            f[k]=max(f[k],f[j]+(ll)t[i]*1000-(ll)w[i]*x); 
        }
    }
    return f[m]>=0;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d%d",&w[i],&t[i]);
    }
    int l=0,r=1000000;
    while(l<=r){
        int mid=l+r>>1;
        if(check(mid)) ans=mid,l=mid+1;
        else r=mid-1;
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值