2017.08.15总结

来源:互联网 发布:领啦试用网站源码 编辑:程序博客网 时间:2024/06/07 03:19

题意:

在给定序列中求出一个区间,最小值是左边界,最大值是右边界。求最大区间长度。

思路:

存下最大值与最小值,然后枚举区间左边界,再用二分法找出满足“最小值是左边界”这个条件的最大区间的右边界编号,然后在这个区间里求出最大值,就是要求的区间了。

#include <iostream>

#include <cstdio>

#include <cstring>

#include <algorithm>

#include <cmath>

using namespace std;

#define N 50050

#define maxn 100050

int a[N];

int index[maxn];

int dpmax[N][20];

int dpmin[N][20];

void makemax(int n)

{

    for(int i=0; i<n; i++)

        dpmax[i][0]=a[i];

    for(int j=1; (1<<j)<=n; j++)

    {

        for(int i=0; i+(1<<j)-1<=n; i++)

        {

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

        }

    }

}

void makemin(int n)

{

    for(int i=0; i<n; i++)

        dpmin[i][0]=a[i];

    for(int j=1; (1<<j)<=n; j++)

    {

        for(int i=0; i+(1<<j)-1<=n; i++)

        {

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

        }

    }

}

int getmax(int l,int r)

{

    int k=(int)(log(r-l+1.0)/log(2.0));

    if(dpmax[l][k]>dpmax[r-(1<<k)+1][k])

        return index[dpmax[l][k]];

    else

        return index[dpmax[r-(1<<k)+1][k]];

}

int getmin(int l,int r)

{

    int k=(int)(log(r-l+1.0)/log(2.0));

    if(dpmin[l][k]>dpmin[r-(1<<k)+1][k])

        return index[dpmin[r-(1<<k)+1][k]];

    else

        return index[dpmin[l][k]];

}

int finds(int l,int r)

{

    int mid;

    int s=l;

    int t=r;

    while(s<t)

    {

        mid=(s+t)>>1;

        if(getmin(l,mid)==l)

            s=mid+1;

        else

            t=mid-1;

    }

    return t;

}

int main()

{

    int n;

    while(scanf("%d",&n)!=EOF)

    {

        memset(dpmax,0,sizeof(dpmax));

        memset(dpmin,0,sizeof(dpmin));

        for(int i=0; i<n; i++)

        {

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

            index[a[i]]=i;

        }

        makemax(n);

        makemin(n);

        int m=0;

        int s,t;

        for(int i=0; i<n-1; i++)

        {

            s=finds(i,n-1);

            t=getmax(i,s);

            if(t-i>m)

                m=t-i;

        }

        if(m==0)

            printf("-1\n");

        else

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

    }

    return 0;

}

练习赛第六题:

递推.

一、当n为奇数时,a[n]=a[n-1];

二、当n为偶数时有两种情况:

1、n=n-2+1+1;

2、n=n/2*2;

所以:a[n]=a[n-2]+a[n/2];

#include<stdio.h>

int a[1000010];

void fun()

{

    int i;

    a[1]=1;

    a[2]=2;

    for(i=3;i<=1000010;i++)

    {

        if(i&1)

            a[i]=a[i-1]%1000000000;

        else

            a[i]=(a[i-2]+a[i/2])%1000000000;

    }

}

int main()

{

    int n;

    fun();

    while(scanf("%d",&n)!=EOF)

    {

        printf("%d\n",a[n]);

    }

}

第一题:

题意:

你的角色从2出发,到3终止,但你要拿到一个4 给3,其中1不能走,0是可以走的路,问最短路的长度是多少?

思路:

两次bfs,分别求出2到4的距离和3到4的距离,求两个距离相加的最小值。

#include<cstdio>

#include<cstring>

#include<queue>

using namespace std;

const int maxn = 1e3 + 10;

#define INF 0x3f3f3f3f

int n, m;

int a[maxn][maxn];

int vis[maxn][maxn];

int d1[maxn][maxn];

int d2[maxn][maxn];

int dx[] = {0, 0, 1, -1};

int dy[] = {1, -1, 0, 0};

vector<pair<int, int> > b;

void bfs(int x, int y, int tt[][maxn]){

    queue<pair<int, int> > q;

    memset(vis, 0, sizeof vis);

    q.push(make_pair(x, y));

    int cnt = 0;

    while(!q.empty()){

        pair<int, int> t = q.front(); q.pop();

        if(a[t.first][t.second] == 4) cnt++;

        if(cnt == b.size()) return;

        for(int i = 0; i < 4; i++){

            int xx = t.first + dx[i];

            int yy = t.second + dy[i];

            if(xx < 0 || xx >= n || yy < 0 || yy >= m) continue;

            if(a[xx][yy] != 1 && !vis[xx][yy]){

                vis[xx][yy] = 1;

                tt[xx][yy] = tt[t.first][t.second] + 1;

                q.push(make_pair(xx, yy));

            }

        }

    }

}

int main(){

    int t1, t2, p1, p2;

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

    for(int i = 0; i < n; i++)

        for(int j = 0; j < m; j++){

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

            if(a[i][j] == 3){

                t1 = i;

                t2 = j;

            }

            if(a[i][j] == 2){

                p1 = i;

                p2 = j;

            }

            if(a[i][j] == 4){

                b.push_back(make_pair(i, j));

            }

        }

    int minn = INF;

    memset(d1, 0, sizeof d1);

    memset(d2, 0, sizeof d2);

    bfs(p1, p2, d1);

    bfs(t1, t2, d2);

    for(int i = 0; i < b.size(); i++){

        int ss = b[i].first, pp = b[i].second;

        if(d1[ss][pp] && d2[ss][pp])

        minn = min(minn, d1[ss][pp] + d2[ss][pp]);

    }

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

}

 

原创粉丝点击