超级码力在线编程大赛初赛 第一场

1.树木规划


贪心即可,最左边第一个不移动,如果之和一个与之前间隔小于d,就移除掉。

class Solution {
public:
    /**
     * @param trees: the positions of trees.
     * @param d: the minimum beautiful interval.
     * @return: the minimum number of trees to remove to make trees beautiful.
     */
     bool check(vector<int> trees,int a,int d)
    {
        int ss=0;
        int last=-1000000000,tmp;
        for(int i=0;i<trees.size();++i)
        {
            tmp=trees[i];
            if(tmp-last>=d)
            last=tmp;
            else
            {
                ss++;
                if(ss>a)
                return false;
            }
        }
        return true;
    }   
    int treePlanning(vector<int> &trees, int d) {
        // write your code here.
    int l,r,mid;
    l=0,r=trees.size()-1;
    int ans=1000000000;
    while(l<=r)
    {
        mid=(l+r)>>1;
        if(check(trees,mid,d))
        {
            ans=min(ans,mid);
            r=mid-1;
        }
        else
        l=mid+1;
    }
    return ans;
    }
};

2.正三角形拼接


因为n>=3,所以只有答案只有可能是0,1,2。如果此时已经有三个一样的,就是0,如果此时有两个一样的,如果还有一个比一样的这个要大,那么就是1,如果现在一个可以分成两个一样的,并且此时场上还有一个一样的,也是1,其它情况都是2。

class Solution {
public:
    /**
     * @param lengths: the lengths of sticks at the beginning.
     * @return: return the minimum number of cuts.
     */
    int makeEquilateralTriangle(vector<int> &lengths) {
        // write your code here.
        map<int,int>mp;
        int a[1001];
        int b[1001];
        int cnt1=0;
        int cnt2=0;
        for(int i=0;i<lengths.size();++i)
        {
            mp[lengths[i]]++;
            if(mp[lengths[i]]==3)
            return 0;
        }
        for(int i=0;i<lengths.size();++i)
        {
            if(mp[lengths[i]]==1)
            a[++cnt1]=lengths[i];
            if(mp[lengths[i]]==2)
            b[++cnt2]=lengths[i];
        }
        sort(a+1,a+1+cnt1);
        sort(b+1,b+1+cnt2);
        sort(lengths.begin(),lengths.end(),greater<int>());
        for(int i=1;i<=cnt2;++i)
        for(int j=0;j<lengths.size();++j)
        {
            if(lengths[j]>b[i])
            return 1;
            else
            break;
        }
        for(int i=1;i<=cnt1;++i)
        {
            for(int j=0;j<lengths.size();++j)
            {
                if(lengths[j]>a[i])
                {
                    if(lengths[j]==a[i]*2)
                    return 1;
                }
                else
                break;
            }
        }
        return 2;
    }
};

3.大楼间穿梭


求右边第一个大于它的,是经典的单调栈模型,预处理完之后,再dp。dp[i]表示到第i个楼的最小消耗体力。就是通过两种方式转移dp[l[i]]=min(dp[l[i]],dp[i]+x),dp[i+2]=min(dp[i+2],dp[i]+y),dp[i+1]=min(dp[i+1],dp[i]+y),最后输出dp[n]即可.

class Solution {
public:
    /**
     * @param heights: the heights of buildings.
     * @param k: the vision.
     * @param x: the energy to spend of the first action.
     * @param y: the energy to spend of the second action.
     * @return: the minimal energy to spend.
     */
    long long shuttleInBuildings(vector<int> &heights, int k, int x, int y) {
        // write your code here.
        int stc[100005];
        int l[100005];
        long long dp[100005];
        memset(stc,0,sizeof(stc));
        memset(l,-1,sizeof(l));
        int h=0;
        int n=heights.size();
        stc[++h]=n;
    l[n]=-1;
    for(int i=n-1;i>=1;i--)
    {
        bool flag=0;
        while(h)
        {
            if(stc[h]-i>k)
            break;
            else
            if(heights[i-1]>heights[stc[h]-1])
            {
                h--;
            }
            else
            {
                l[i]=stc[h];
                flag=1;
                break;
            }
        }
        if(!flag)
        l[i]=-1;
        stc[++h]=i;
    }
    for(int i=1;i<=n;++i)
    dp[i]=1e15;
    dp[1]=0;
    for(int i=1;i<n;++i)
    {
        if(l[i]!=-1)
        dp[l[i]]=min(dp[l[i]],dp[i]+x);
        if(i<=n-2)
        {
            dp[i+1]=min(dp[i+1],dp[i]+y);
            dp[i+2]=min(dp[i+2],dp[i]+y);
        }
        if(i<=n-1)
        dp[i+1]=min(dp[i+1],dp[i]+y);
    }
    return dp[n];
    }
};

4.对称前后缀


可以暴力,我们枚举中间元素为起点,向外扩,更新答案。我们发现,只有aba,abba这两种状态,其它状态都可以在扩的过程中出现。所以枚举,以i为中心,或者以i,i+1为中心,像两边扩。如果两边相等,长度+1,如果此时是回文串,那么就贡献子串的长度。

class Solution {
public:
    /**
     * @param s: a string.
     * @return: return the values of all the intervals.
     */
    long long suffixQuery(string &s) {
        // write your code here
        int len=s.length();
    long long ans=0;
    for(int i=0;i<len;++i)
    {
        ans++;
        int l=i-1;
        int r=i+1;
        int length=0;
        while(l>=0&&r<=len-1)
        {
            int d=r-l+1;
            if(s[l]==s[r])
            {
                length++;
                if(d==2*length+1)
                ans+=d;
                else
                ans+=length;
            }
            else
            length=0;
            l--;
            r++;
        }
        if(i+1<len)
        {
            length=0;
            if(s[i]==s[i+1])
            {
                ans+=2;
                length=1;
            }
            l=i-1;
            r=i+2;
            while(l>=0&&r<=len-1)
            {
                int d=r-l+1;
                if(s[l]==s[r])
                {
                    length++;
                    if(d==2*length)
                    ans+=d;
                    else
                    ans+=length;
                }
                else
                length=0;
                l--;
                r++;
            }
        }
    }
    return ans;
    }
};

猜你喜欢

转载自blog.csdn.net/weixin_44491423/article/details/108298824