码迷,mamicode.com
首页 > 其他好文 > 详细

topcoder srm 681 div1 -3

时间:2017-06-13 20:40:56      阅读:210      评论:0      收藏:0      [点我收藏+]

标签:区间   stack   check   出队   ext   limited   不能   ack   开始   

1、一个机器人有$m$个部分。有$n$台机器,第$i$个机器可以生产编号为$[a_{i},b_{i}]$区间的部分,最多可以生产$k_{i}$个部分。最多可以组装成多少个机器?

思路:二分答案。然后判断。将所有的机器按照$a_{i}$排序,$a_{i}$相同的按照$b_{i}$排序。用一个优先队列维护这些机器。这样对于第$i$个部分,拿出队列开始的机器来生产该部分;如果队列开头的机器生产的部分没用完,则将其左区间$a_{t}$设置为$a_{t}+1$然后重新塞到队列里。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;

const int N=10000000;


int n,m;
int c[N],a[N],b[N];


struct node
{
    int L,R,cnt;

    node(){}
    node(int _L,int _R,int _cnt):L(_L),R(_R),cnt(_cnt) {}

    int operator<(const node& A) const
    {
        if(L!=A.L) return L>A.L;
        return R>A.R;
    }
};

priority_queue<node> Q;

int check(const int M)
{
    if(!M) return 1;
    while(!Q.empty()) Q.pop();
    for(int i=1;i<=n;++i) Q.push(node(a[i],b[i],c[i]));
    for(int i=1;i<=m;++i)
    {
        if(Q.empty()) return 0;
        int sum=0;
        while(sum<M)
        {
            if(Q.empty()) return 0;
            if(Q.top().L!=i) return 0;
            if(sum+Q.top().cnt<=M)
            {
                sum+=Q.top().cnt;
                Q.pop();
            }
            else
            {
                node p=Q.top(); Q.pop();
                p.cnt-=M-sum;
                ++p.L;
                if(p.L<=p.R) Q.push(p);
                break;
            }
        }
        while(!Q.empty()&&Q.top().L==i)
        {
            node p=Q.top(); Q.pop();
            ++p.L;
            if(p.L<=p.R) Q.push(p);
        }
    }
    return 1;
}

class FleetFunding
{
public:
    int maxShips(int mm,vector<int> kk,vector<int> aa,vector<int> bb)
    {
        n=(int)kk.size();
        m=mm;
        int sum=0;
        for(int i=1;i<=n;++i)
        {
            c[i]=kk[i-1];
            a[i]=aa[i-1];
            b[i]=bb[i-1];
            sum+=c[i];
        }
        int low=0,high=sum/m;
        int ans=0;
        while(low<=high)
        {
            int M=(low+high)>>1;
            if(check(M)) ans=max(ans,M),low=M+1;
            else high=M-1;
        }
        return ans;
    }
};

2、一个长度为$n$的数组$A$,$B_{i}=max(k|A_{i-k}<A_{i}$且$A_{i+k}<A_{i})$。返回$\sum_{i=0}^{n-1}B_{i}$。给定$0\leq x_{0},a,b < 2^{50}$。数组$A$的产生方式如下。这个题目要求内存大小是$O(1)$,即不能开数组存储$A$。

A[0] = x0
for i = 1 to n-1:
        A[i] = ((A[i-1] XOR a) + b) AND ((2^50) - 1)

 思路:首先由$A_{i}$得到$A_{i-1}$的方式为$A_{i-1}=((A_{i}+2^{50}-b)$^$a)$&$(2^{50}-1)$。然后就是一个数字一个数字暴力计算$B$值。总的累积复杂度是$O(n)$的。

#include <stdio.h>
#include <string.h>
#include <string>
#include <iostream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <algorithm>
#include <stack>
#include <assert.h>
using namespace std;

const int mod=1000000007;
const long long M=(1ll<<50)-1;

long long a,b;

long long NextX(long long x)
{
    return ((x^a)+b)&M;
}


long long PreX(long long x)
{
    return ((x+M+1-b)^a)&M;
}

int cal(int id,long long x,int n)
{
    int ll=id,rr=id;
    int ans=0;
    long long lx=x,rx=x;
    while(ll-1>=0&&rr+1<n)
    {
        lx=PreX(lx);
        rx=NextX(rx);
        if(lx<x&&x>rx) ++ans,--ll,++rr;
        else break;
    }
    return ans;
}

class LimitedMemorySeries2
{
public:
    int getSum(int n,long long x0,long long aa,long long bb)
    {
        a=aa;
        b=bb;
        int ans=0;
        long long t=x0;
        for(int i=0;i<n;++i)
        {
            ans+=cal(i,t,n);
            if(ans>=mod) ans-=mod;
            t=NextX(t);
        }
        return ans;
    }
};

  

topcoder srm 681 div1 -3

标签:区间   stack   check   出队   ext   limited   不能   ack   开始   

原文地址:http://www.cnblogs.com/jianglangcaijin/p/7003187.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!