Codeforces Beta Round #6 (Div. 2 Only)

A,B,C都是水题。。。

D题,直接爆搜。我换了好多姿势,其实最简单的方法,就能过。

#include <cstdio>

#include <string>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <ctime>

#include <queue>

#include <vector>

#include <map>

#include <set>

#include <algorithm>

#include <iostream>

using namespace std;

int que[50];

int p[50];

int o[50];

int temp[50];

int st[50];

int ans,minz;

int n,a,b;

void dfs(int x,int sum)

{

    int i;

    if(sum >= minz) return;

    if(x == n)

    {

        for(i = 1;i <= n;i ++)

        temp[i] = p[i];

        for(i = 2;i <= n-1;i ++)

        {

            temp[i] -= o[i]*a;

            temp[i-1] -= o[i]*b;

            temp[i+1] -= o[i]*b;

        }

        for(i = 2;i <= n-1;i ++)

        {

            if(temp[i] >= 0) break;

        }

        if(i == n)

        {

            if(sum < minz)

            {

                minz = sum;

                for(i = 2;i <= n-1;i ++)

                st[i] = o[i];

            }

        }

        return ;

    }

    for(i = 0;i <= 8;i ++)

    {

        o[x] = i;

        dfs(x+1,sum+i);

    }

}

int main()

{

    int i,j;

    scanf("%d%d%d",&n,&a,&b);

    for(i = 1; i <= n; i ++)

    {

        scanf("%d",&p[i]);

    }

    while(p[1] >= 0)

    {

        que[ans++] = 2;

        p[1] -= b;

        p[2] -= a;

        p[3] -= b;

    }

    while(p[n] >= 0)

    {

        que[ans++] = n-1;

        p[n-2] -= b;

        p[n] -= b;

        p[n-1] -= a;

    }

    for(i = 1;i <= n;i ++)

    {

        if(p[i] >= 0) break;

    }

    if(i == n+1)

    {

        printf("%d\n",ans);

        for(i = 0;i < ans;i ++)

        printf("%d ",que[i]);

        printf("\n");

        return 0;

    }

    minz = 1000;

    dfs(2,0);

    printf("%d\n",minz+ans);

    for(i = 0;i < ans;i ++)

    printf("%d ",que[i]);

    for(i = 2;i <= n-1;i ++)

    {

        for(j = 1;j <= st[i];j ++)

        printf("%d ",i);

    }

    printf("\n");

    return 0;

}
View Code

 E题,二分+rmq之类的,能求区间最值的算法。

题意是比较扯,按章节排列的n本书,要展示,最长能展示多少本,这一段的高度差要小于等于k,再输出总共多少中情况,把起点,终点输出。

rmq好久没写过了啊,记不得 什么东西了。

#include <cstdio>

#include <string>

#include <cstring>

#include <cmath>

#include <cstdlib>

#include <ctime>

#include <queue>

#include <vector>

#include <map>

#include <set>

#include <algorithm>

#include <iostream>

using namespace std;

int n,k;

int p[100001];

int dpmin[22][100001];

int dpmax[22][100001];

int bin[30];

void CL(int n)

{

    int i,j;

    for(i = 1;i <= n;i ++)

    {

        dpmin[0][i] = p[i];

        dpmax[0][i] = p[i];

    }

    for(i = 1;bin[i] <= n;i ++)

    {

        for(j = 1;j + bin[i-1] <= n;j ++)

        {

            dpmin[i][j] = min(dpmin[i-1][j],dpmin[i-1][j+bin[i-1]]);

            dpmax[i][j] = max(dpmax[i-1][j],dpmax[i-1][j+bin[i-1]]);

        }

    }

}

int rmqmax(int s,int t)

{

    int k = log((t-s+1)*1.0)/log(2.0);

    return max(dpmax[k][s],dpmax[k][t-bin[k]+1]);

}

int rmqmin(int s,int t)

{

    int k = log((t-s+1)*1.0)/log(2.0);

    return min(dpmin[k][s],dpmin[k][t-bin[k]+1]);

}

int query(int s,int t)

{

    return rmqmax(s,t) - rmqmin(s,t);

}

int judge(int mid)

{

    int i,ans = 0;

    for(i = 1;i <= n-mid+1;i ++)

    {

        if(query(i,i+mid-1) <= k)

        ans ++;

    }

    return ans;

}

int main()

{

    int i,j,str,end,mid;

    scanf("%d%d",&n,&k);

    for(i = 1;i <= n;i ++)

    scanf("%d",&p[i]);

    bin[0] = 1;

    for(i = 1;i <= 22;i ++)

    bin[i] = bin[i-1]*2;

    CL(n);

    str = 1;

    end = n;

    while(str < end)

    {

        mid = (str + end + 1)/2;

        if(judge(mid))

        str = mid;

        else

        end = mid - 1;

    }

    printf("%d %d\n",end,judge(end));

    for(i = 1;i <= n-end+1;i ++)

    {

        if(query(i,i+end-1) <= k)

        {

            printf("%d %d\n",i,i+end-1);

        }

    }

    return 0;

}
View Code

 

 

你可能感兴趣的:(codeforces)