USACO 2018JAN Silver

123 篇文章 0 订阅
53 篇文章 0 订阅

A.lifeguards(线段树+枚举)
枚举删掉哪条线段,离散化+线段树维护线段覆盖长度qaq
B.rental(贪心+二分+枚举)
枚举留几头牛,贪心算收益qaq
C.mootube(并查集+暴力)
类似最大生成树的并查集+暴力处理出dis,然后暴力回答询问qaq

A

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,a[N<<1],L[N],R[N],num=0,m,ans=0;
struct node{
    int len,covlen,cov;
}tr[N<<4];
inline void pushup(int p){
    if(tr[p].cov) return;
    tr[p].covlen=tr[p<<1].covlen+tr[p<<1|1].covlen;
}
inline void build(int p,int l,int r){
    if(l==r){tr[p].len=a[l+1]-a[l];return;}
    int mid=l+r>>1;
    build(p<<1,l,mid);build(p<<1|1,mid+1,r);
    tr[p].len=tr[p<<1].len+tr[p<<1|1].len;
}
inline void cover(int p,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        tr[p].cov++;
        if(tr[p].cov==1) tr[p].covlen=tr[p].len;return;
    }int mid=l+r>>1;
    if(x<=mid) cover(p<<1,l,mid,x,y);
    if(y>mid) cover(p<<1|1,mid+1,r,x,y);
    pushup(p);
}
inline void del(int p,int l,int r,int x,int y){
    if(x<=l&&r<=y){
        tr[p].cov--;
        if(tr[p].cov==0){
            if(l==r) tr[p].covlen=0;
            else pushup(p);
        }return;
    }int mid=l+r>>1;
    if(x<=mid) del(p<<1,l,mid,x,y);
    if(y>mid) del(p<<1|1,mid+1,r,x,y);
    pushup(p);
}
int main(){
    freopen("lifeguards.in","r",stdin);
    freopen("lifeguards.out","w",stdout);
    n=read();
    for(int i=1;i<=n;++i){
        a[++num]=L[i]=read();a[++num]=R[i]=read();
    }sort(a+1,a+num+1);m=unique(a+1,a+num+1)-a-1;build(1,1,m-1);
    for(int i=1;i<=n;++i){
        L[i]=lower_bound(a+1,a+m+1,L[i])-a;
        R[i]=lower_bound(a+1,a+m+1,R[i])-a;
        cover(1,1,m-1,L[i],R[i]-1);
    }for(int i=1;i<=n;++i){
        del(1,1,m-1,L[i],R[i]-1);
        ans=max(ans,tr[1].covlen);
        cover(1,1,m-1,L[i],R[i]-1);
    }printf("%d\n",ans);
    return 0;
}

B

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,r,a[N],b[N];
ll suma[N],sumb[N],sumx[N],sumc[N],ans=0;
struct node{
    int x,c;
}s[N];
inline bool cmp(int x,int y){return x>y;}
inline bool cmp1(node x,node y){return x.c>y.c;}
int main(){
    freopen("rental.in","r",stdin);
    freopen("rental.out","w",stdout);
    n=read();m=read();r=read();
    for(int i=1;i<=n;++i) a[i]=read();
    sort(a+1,a+n+1,cmp);
    for(int i=1;i<=n;++i) suma[i]=suma[i-1]+a[i];
    for(int i=1;i<=m;++i) s[i].x=read(),s[i].c=read();
    sort(s+1,s+m+1,cmp1);
    for(int i=1;i<=m;++i) sumx[i]=sumx[i-1]+s[i].x,sumc[i]=sumc[i-1]+(ll)s[i].c*s[i].x;
    for(int i=1;i<=r;++i) b[i]=read();
    sort(b+1,b+r+1,cmp);
    for(int i=1;i<=r;++i) sumb[i]=sumb[i-1]+b[i];
    for(int i=0;i<=n;++i){//留i头牛的最优收益
        if(n-i>r) continue;
        ll res=sumb[n-i];
        int pos=upper_bound(sumx+1,sumx+m+1,suma[i])-sumx-1;
        res+=sumc[pos];
        if(pos!=m) res+=(ll)s[pos+1].c*(suma[i]-sumx[pos]);
        ans=max(ans,res);
    }printf("%lld\n",ans);
    return 0;
}

C

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 5010
inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x*f;
}
int n,m,dis[N][N],fa[N],sz[N];
vector<int>a[N];
struct edge{
    int x,y,val;
}e[N];
inline bool cmp(edge x,edge y){return x.val>y.val;}
inline int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
int main(){
    freopen("mootube.in","r",stdin);
    freopen("mootube.out","w",stdout);
    n=read();m=read();
    for(int i=1;i<=n;++i) fa[i]=i,a[i].push_back(i);
    for(int i=1;i<n;++i) e[i].x=read(),e[i].y=read(),e[i].val=read();
    sort(e+1,e+n,cmp);
    for(int ii=1;ii<=n-1;++ii){
        int xx=find(e[ii].x),yy=find(e[ii].y);
        if(a[xx].size()>a[yy].size()) swap(xx,yy);
        fa[xx]=yy;
        for(int i=0;i<a[xx].size();++i)
            for(int j=0;j<a[yy].size();++j){
                int x=a[xx][i],y=a[yy][j];
                dis[x][y]=dis[y][x]=e[ii].val;
            }
        for(int i=0;i<a[xx].size();++i) a[yy].push_back(a[xx][i]);
    }while(m--){
        int k=read(),x=read(),ans=0;
        for(int i=1;i<=n;++i) if(dis[x][i]>=k) ans++;
        printf("%d\n",ans);
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值