Zut_round 6 部分题题解

A - LIS O(n^2) 模板
  最长上升子序列,两种做法
    1,O(n^2)   两层循环,依次遍历
    2,O(nlogn)   一层循环,用二分

#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxx=100019;
int a[10109],ans[10109];
int main()
{
    int i,j,n;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);ans[i]=1;
    }
    for(i=2; i<=n; i++)
    {
        for(j=1; j<i; j++)
        {
            if(a[i]>a[j])
                ans[i]=max(ans[i],ans[j]+1);
        }
    }
    sort(ans+1,ans+1+n);
    printf("%d\n",ans[n]);
    return 0;
}

B - 一维线性dp ++ HDU - 2059
  dp到达每个充电站的最短时间(类似第一题,只是判断的条件不同),一个小细节是最开始的时候车子有电,相当于充电了,但不能算时间
  一开始有个疑惑:到达一个充电站后车子可能还有电,下一段会先高速行驶啊?
这里是包括这种情况的,假设到第Pn个充电站了还有电,但我们在遍历第Pn-1个充电站时,会先以高速行驶C米到达当前dp点,这样就 包含了上面的问题(状态转移的巧妙)

dp接触的太少,找了几个题一维dp的题,跟大家分享一下

HDU
1087   1257   1003   1800   1025   1160   2517   3998


#include<stdio.h>
int p[102];
double dp[102];
int main()
{
    int i,j,l,n,c,t,vr,v1,v2,len;
    double min,e;
    while(scanf("%d",&l)!=EOF)
    {
        scanf("%d%d%d%d%d%d",&n,&c,&t,&vr,&v1,&v2);
        dp[0]=p[0]=0;
        for(i=1; i<=n; i++)
            scanf("%d",&p[i]);
        p[i]=l;
        for(i=1; i<n+2; i++)
        {
            min=999999999;
            for(j=0; j<i; j++)
            {
                len=p[i]-p[j];
                if(len>c)
                    e=1.0*c/v1+(len-c+0.)/v2;
                else
                    e=1.0*len/v1;
                e+=dp[j];
                if(j)
                    e+=t;
                if(min>e)
                    min=e;
            }
            dp[i]=min;
        }
        if(1.0*l/vr>dp[n+1])
            printf("What a pity rabbit!\n");
        else
            printf("Good job,rabbit!\n");
    }
}

C - Frog Jumping CodeForces - 1077A
   由于向左与向右是交替的,所以向左和向右两次看作一组运动,判断k的奇偶性再相加减即可。
(突然想到一个题,也是在坐标轴上跳,队列的一个经典题)

题目链接  http://poj.org/problem?id=3278

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int maxx=300019;
int main()
{

    ll a,b,k,t;
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld%lld%lld",&a,&b,&k);
        if(k%2==0)
        {
            printf("%lld\n",(a-b)*(k/2));
        }
        else
        {
            printf("%lld\n",(a-b)*(k/2)+a);
        }
    }
    return 0;
}

D - Disturbed People CodeForces - 1077B
  直接遍历模拟一下即可,符合条件的时候要把后方的灯关掉

#include <bits/stdc++.h>
using namespace std;
const int maxx=100017;
int a[100];
int main()
{
    int i,n,ans=0;
    scanf("%d",&n);
    for(i=1; i<=n; i++)
        scanf("%d",&a[i]);
    for(i=2; i<n; i++)
    {
        if(a[i]==0&&a[i-1]==1&&a[i+1]==1)
        {
            ans++;
            a[i+1]=0;
        }
    }
    printf("%d\n",ans);
    return 0;
}

E - Good Array CodeForces - 1077C
  首先找到数组的最大值和第二大的值,然后遍历数组,判断是否是最大值值分两种情况讨论,开个数组储存符合题意的下标,最后输出即可。

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int maxx=200017;
ll a[maxx],b[maxx];
int pos=0;
ll ans[maxx];
int main()
{
    ll i,n,sum=0;
    scanf("%lld",&n);
    for(i=1; i<=n; i++)
    {
        scanf("%d",&a[i]);
        b[i]=a[i];
        sum+=a[i];
    }
    sort(b+1,b+1+n);
    for(i=1; i<=n; i++)
    {
        if(a[i]==b[n])
        {
            if(b[n-1]*2==(sum-b[n]))
            {
                ans[++pos]=i;
            }
        }
        else
        {
            if(b[n]*2==(sum-a[i]))
            {
                ans[++pos]=i;
            }
        }

    }
    printf("%d\n",pos);
    if(pos>=1)
        printf("%lld",ans[1]);
    for(i=2; i<=pos; i++)
        printf(" %lld",ans[i]);
    return 0;
}

未完待续。。。。。。

上一篇:「LibreOJ β Round #3」绯色 IOI(危机)(单调栈+动态规划+复杂度分析)


下一篇:【Exgcd】斩杀线计算大师