zoukankan      html  css  js  c++  java
  • [USACO 2018 Open Gold] Tutorial

    Link:

    传送门

    A:

    对于每一条分割线,设本不应在其左侧的个数为$x$

    重点要发现每次一来一回的操作恰好会将一对分别应在左/右侧的一个数从右/左移过去

    这样就转直接用树状数组求出最大的$x$即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    typedef long long ll;
    typedef pair<int,int> P;
    const int MAXN=1e5+10;
    //res至少为1 
    int n,bit[MAXN],res=1;P dat[MAXN];
    
    void Update(int x)
    {while(x<=n) bit[x]++,x+=x&(-x);}
    int Query(int x)
    {
        int ret=0;
        while(x) ret+=bit[x],x-=x&(-x);
        return ret;
    }
    
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%d",&dat[i].X),dat[i].Y=i;
        sort(dat+1,dat+n+1);
        
        for(int i=1;i<n;i++)
            Update(dat[i].Y),res=max(res,i-Query(i));
        printf("%d",res);
        return 0;
    }
    Problem A

    冒泡排序相关题多考虑数与数相对位置以及每个数应在的位置

    B:

    发现答案具有单调性后首先想到二分答案或是直接枚举

    由于不用重复建图,直接枚举看起来能更快一些,不过好像并不能在线$O(logn)$判断是否出现了环……

    (按照杨主力的指示还是在google上搜到了论文,不过并不打算学传送门

    剩下就是优先队列套拓扑排序就行了

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second
    #define pb push_back
    typedef long long ll;
    typedef pair<int,int> P;
    typedef double db;
    const int MAXN=1e5+10;
    vector<int> dat[MAXN];
    struct edge{int nxt,to;}e[MAXN<<2];
    int n,m,num,x,head[MAXN],res[MAXN],in[MAXN],tot;
    
    void add_edge(int x,int y)
    {e[++tot].nxt=head[x];e[tot].to=y;head[x]=tot;}
    void build(int x)
    {
        tot=0;
        memset(in,0,sizeof(in));
        memset(head,0,sizeof(head));
        for(int i=1;i<=x;i++)
            for(int j=0;j<dat[i].size()-1;j++)
                add_edge(dat[i][j],dat[i][j+1]),in[dat[i][j+1]]++;
    }
    bool check()
    {
        int sz=0;
        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 t=q.top();q.pop();
            res[++sz]=t;
            for(int i=head[t];i;i=e[i].nxt)
            {
                in[e[i].to]--;
                if(!in[e[i].to]) q.push(e[i].to);
            }
        }
        return (sz==n);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&num);
            for(int j=1;j<=num;j++)
                scanf("%d",&x),dat[i].pb(x);
        }
        
        int l=1,r=m;
        while(l<=r)
        {
            int mid=(l+r)>>1;
            build(mid);
            if(check()) l=mid+1;
            else r=mid-1;
        }
        build(r);check();
        for(int i=1;i<=n;i++)
            printf("%d ",res[i]);
        return 0;
    }
    Problem B

    C:

    明显0/1分数规划,每次$dp$找当前重量大于等于$m$的最大权值和即可

    一篇很好的博客,图解0/1分数规划:传送门

    顺便学了下$Dinkelbach$算法,发现就是每次找到最大值时直接跳到该方案的零点处

    直到该方案的零点为当前$x$下的最大值时停止即可

    #include <bits/stdc++.h>
    
    using namespace std;
    #define X first
    #define Y second 
    typedef long long ll;
    typedef pair<int,int> P;
    typedef double db;
    const int MAXN=1e5+10;
    int n,m,w[MAXN],t[MAXN];
    db l,r,a[MAXN],dp[MAXN];
    
    bool check(db x)
    {
        for(int i=1;i<=n;i++)
            a[i]=t[i]-1.0*x*w[i];
        for(int i=1;i<=m;i++) dp[i]=-1e9;    
        
        for(int i=1;i<=n;i++)
            for(int j=m;j>=0;j--)
                dp[min(m,j+w[i])]=max(dp[min(m,j+w[i])],dp[j]+a[i]);
        return dp[m]>=0;
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
            scanf("%d%d",&w[i],&t[i]),r+=t[i];
        
        while(fabs(l-r)>1e-6)
        {
            db mid=(l+r)/2.0;
            if(check(mid)) l=mid;
            else r=mid;
        }
        printf("%d",int((l+r)*500));
        return 0;
    }
    Problem C
  • 相关阅读:
    接口的显示实现和隐式实现
    Math.Round和四舍五入
    经典SQL语句大全(转)
    简明添加log4net到项目中
    NAnt学习笔记(3) Properties, Loggers & Listeners
    (转)Groupon前传:从10个月的失败作品修改,1个月找到成功
    Pyramid中如何配置多种URL匹配同一个View
    《IT项目管理》读书笔记(4) —— 项目范围管理
    C#语法糖
    枚举类型转换成字符串
  • 原文地址:https://www.cnblogs.com/newera/p/9603979.html
Copyright © 2011-2022 走看看