cf 424

Office Keys

首先显然有随人位置的递增,钥匙的位置也要递增,这样考虑两张做法:

1.$f(i,j)$ 表示前i个人,钥匙到第j个最少用的最大时间,然后$O(nK)$ dp

2.二分时间,对于每一个人选择当前能选择的最左面的钥匙 $O((n+K) logn)$

#include <bits/stdc++.h>

#define LL long long

const int N = 2010;

using namespace std;

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

int Abs(int x)
{
    if(x<0) return -x;
    return x;
}

int p;

bool check(int tim)
{
    int j = 1;
    for(int i=1;i<=n;i++)
    {
        while(j<=m && Abs(a[i]-b[j])+(LL)Abs(b[j]-p) > tim) j++;
        if(j>m) return 0;
        else j++;
    }
    return 1;
}

int main()
{
    int maxv = 0;
    scanf("%d%d%d",&n,&m,&p);
    maxv = p;
    for(int i=1;i<=n;i++) scanf("%d",&a[i]), maxv = max(maxv ,a[i]);
    for(int i=1;i<=m;i++) scanf("%d",&b[i]), maxv = max(maxv, b[i]);
    sort(a+1,a+n+1);
    sort(b+1,b+m+1);
    int l=0, r=0;
    for(int i=1;i<=n;i++) l = max(l, Abs(p-a[i]));
    for(int i=1;i<=n;i++) r = max(r, Abs(b[i]-a[i]) + Abs(p-b[i]));
    while(r-l>5)
    {
        int mid = (l+(LL)r)>>1LL;
        if(check(mid)) r = mid;
        else l = mid;
    }
    for(int i=l;i<=r;i++)
        if(check(i))
        {
            cout<<i<<endl;
            break;
        }
    return 0;
}

Cards Sorting

方法1:直接用splay模拟。

方法2:考虑每次删掉当前最小数的代价是上一个最小数和它之间的循环dist,BIT或链表即可。

#include <bits/stdc++.h>

const int N = 100010;
#define INF 0x3f3f3f3f
#define LL long long

using namespace std;

struct node
{
    node *ch[2];
    int v, sum, minv;
    int cmp(int x)
    {
        if(ch[0]->sum + 1 == x) return -1;
        return x > ch[0]->sum;
    }
    node* init(int x);
    void update()
    {
        sum = ch[0]->sum + ch[1]->sum + 1;
        minv = min(v, min(ch[0]->minv, ch[1]->minv));
    }
}spT[N], Null, *root;

int tot=0;

node* node::init(int x)
{
    v=x;
    minv=x;
    ch[0]=ch[1]=&Null;
    sum=1;
    return this;
}

node* build(int src[],int l,int r)
{
    if(l==r) return spT[++tot].init(src[l]);
    int mid=(l+r)>>1;
    node* tmp=spT[++tot].init(src[mid]);
    if(l<mid) tmp->ch[0]=build(src,l,mid-1);
    if(mid<r) tmp->ch[1]=build(src,mid+1,r);
    tmp->update();
    return tmp;
}

void rot(node* &o,int x)
{
    node* tmp=o->ch[x];
    o->ch[x]=tmp->ch[x^1];
    tmp->ch[x^1]=o;
    o->update();
    o=tmp;
    o->update();
}

void splay(node* &o,int k)
{
    int t=o->cmp(k);
    if(t==-1) return;
    if(t) k-=o->ch[0]->sum+1;
    int t1=o->ch[t]->cmp(k);
    if(~t1)
    {
        if(t1) k-=o->ch[t]->ch[0]->sum+1;
        splay(o->ch[t]->ch[t1],k);
        if(t1==t) rot(o,t);
        else rot(o->ch[t],t1);
    }
    rot(o,t);
}

int find_min(node *&o,int minv,int now)
{
    if(o->ch[0]->minv == minv) return find_min(o->ch[0],minv,now);
    else
    {
        if(o->v == minv) return now+o->ch[0]->sum;
        return find_min(o->ch[1],minv,now+o->ch[0]->sum+1);
    }
}

int n,a[N];

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    Null.minv = INF;
    a[0]=INF;
    a[n+1]=INF;
    root = build(a,0,n+1);
    int len = n+2;
    LL ans = 0;
    for(int i=1;i<=n;i++)
    {
        int tmp = find_min(root,root->minv,0);
        ans += (LL)tmp;
        splay(root,1);
        splay(root->ch[1],tmp+1);
        node* tp = root->ch[1]->ch[0];
        root->ch[1]->ch[0] = &Null;
        root->ch[1]->update();
        root->update();

        splay(tp,tp->sum);
        tp = tp->ch[0];
        len--;

        splay(root,len-tp->sum);
        splay(root->ch[0],len-tp->sum-1);
        root->ch[0]->ch[1] = tp;
        root->ch[0]->update();
        root->update();
    }
    cout << ans << endl;
    return 0;
}

Bamboo Partition

显然要满足的条件等价于

$\sum_{i=1}^n { [\frac{a_i + d - 1}{d}] \cdot d - a_i} \leq K$

$F(d) = \sum_{i=1}^n { [\frac{a_i - 1}{d}] + 1} \cdot d  \leq K + \sum {a_i}$

固定 $\sum_{i=1}^n { [\frac{a_i - 1}{d}] + 1}$,从而 $F(d)$ 单调。

对于前者直接找出所有得数相同的 $d$ 的区间,逐一计算即可。

复杂度$O(n^2 \sqrt {a_i} )$

通过调参可以 $O(n \sqrt {a_{max} n})$

#include <bits/stdc++.h>

#define LL long long

const int N = 110;

using namespace std;

int n,tot,a[N];
LL K;
vector<int> v;

int main()
{
    cin>>n>>K;
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        K += (LL)a[i];
        int j=1;
        int tmp = a[i]-1;
        if(tmp>0)
        {
            for(int i=1;i<=tmp;i=j+1)
                j = tmp/(tmp/i), v.push_back(i);
            v.push_back(tmp+1);
        }
    }
    v.push_back(1);
    sort(v.begin(),v.end());
    v.resize(distance(v.begin(), unique(v.begin(), v.end())));
    LL ans = 1, sum;
    for(int i=0;i<(int)v.size() - 1;i++)
    {
        int l = v[i], r = v[i+1]-1;
        sum = 0;
        for(int j=1;j<=n;j++) sum += (a[j]-1LL)/l + 1LL;
        LL tmp = min(K/sum, (LL)r);
        if(tmp>=l) ans = tmp;
    }
    LL l = v[v.size()-1];
    LL tmp = K/n;
    if(tmp >= l) ans = tmp;
    cout << ans << endl;
}

时间: 2024-08-08 17:52:10

cf 424的相关文章

/etc/postfix/main.cf

# cat main.cf     1  # Global Postfix configuration file. This file lists only a subset     2  # of all parameters. For the syntax, and for a complete parameter     3  # list, see the postconf(5) manual page (command: "man 5 postconf").     4  #

微信 {&quot;errcode&quot;:40029,&quot;errmsg&quot;:&quot;invalid code, hints: [ req_id: Cf.y.a0389s108 ]&quot;}

{"errcode":40029,"errmsg":"invalid code, hints: [ req_id: Cf.y.a0389s108 ]"} 问题:微信网页授权后,获取到 openid 了,一刷新又没了 微信网页授权获取到的 code 只能使用一次(5分钟内有效),使用一次后,马上失效. 页面授权跳转成功,根据 code 也换取到 openid 了. 此时刷新页面,并不会再次进行授权,而是直接刷新了一下上一次授权跳转后的链接,带的还是

CF with friends and user&#39;s influence considered on NYC data(updated Aug,11st)

Here is the code link: https://github.com/FassyGit/LightFM_liu/blob/master/U_F1.py I use NYC data as other experimens. The split of the training data was seperated by the timeline, and I have normalised the interaction matrix by replacing the checkin

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

Codeforces Round #424 (Div. 2, rated, based on VK Cup Finals)

D题fst了,生无可恋.第二场rated的CF,打得精神恍惚 A. Unimodal Array 题意:判断数列是否是单峰的. 像题意那样分为三个阶段随便判一判就好了 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> using namespace std; int n,x[105],part=1; bool f=1; int main() { scanf(&quo

CF 750

今天CF打的块残废了     就是一废物 A 在24点之前到 直接模拟即可 #include<stdio.h> #include<algorithm> #include<cstring> #include<string> #include<cmath> using namespace std; #define LL long long #define MAXN 1010 #define inf 1000000000.0 int main() {

CF #394 (2) 5/6

Codeforces Round #394 (Div. 2) 总结:有毒的一场比赛.做了三题,结果A被叉,B.C挂综测,还hack失败一发,第一次在CF体会到了-50分的感觉..不知道是不是人品好,比赛时room炸了,然后,unrated.. A  水题,判一下0 0,然后abs(a-b)<=1 B  水题,组个间距比较一下,但一个数的时候要判一下 C  直接暴力上的题 D  也是xjb暴力 题意:给出n,l,r, a[], p[],另有两个数组b[], c[],ci=bi-ai.l<=ai,

一场CF的台前幕后(上)——转

前奏 大约4月份的时候,业界毒瘤pyx噔噔噔跑过来说:“酷爱!我YY了一道题!准备当CF的C” 我当时就被吓傻了."Yet another Chinese round?" “区间取模,区间求和” 感觉这题还不错?不过pyx嫌水了…… 好办!当时我刚刚出完动态仙人掌不久,于是一拍脑袋说:把这个问题出到仙人掌上去! 当然被pyx鄙视了…… 后来一直就没啥动静,直到5月底的CTSC. 试机的时候pyx给我看了套他出的神题……里面有一道题……我不小心读成了下面这个样子: “给定n个m维的模2意