IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> CodeCraft-22 and Codeforces Round #795 (Div. 2) -> 正文阅读

[数据结构与算法]CodeCraft-22 and Codeforces Round #795 (Div. 2)

Dashboard - CodeCraft-22 and Codeforces Round #795 (Div. 2) - Codeforceshttps://codeforces.com/contest/1691

目录

A. Beat The Odds

B. Shoe Shuffling

C. Sum of Substrings

D. Max GEQ Sum


A. Beat The Odds

问最少删除几个,可以让所给数组相邻的两个值的和均为偶数.

思路:

已知偶数+偶数=偶数,奇数+奇数=偶数,奇数+偶数=奇数.所以,只要剩下的都是奇数或者偶数即可.即删去所有的奇数或者偶数.

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
void solve()
{
    int x,n,ou=0,ji=0;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&x);
        if(x%2==0)
        {
            ou++;
        }
        else if(x%2==1)
        {
            ji++;
        }
    }
    printf("%lld\n",min(ou,ji));
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

B. Shoe Shuffling

有n个人,他们每个人有一双鞋.且鞋子的排列是非递减的.问是否存在一种情况,每个人得到不是自己的鞋子,且新鞋子的尺码大于或者等于旧鞋子的尺码.

思路:

只要每一种尺码的鞋子不少于两双就可以实现.把尺码相同的鞋子交换即可.做法就是把相同的鞋子分为一块,然后在这个块内进行颠倒顺序即可.

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
int arr[100005];
map<int,int>ma;
void solve()
{
    ma.clear();
    int n;
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&arr[i]);
        ma[arr[i]]++;
    }
    if(n==1)
    {
        cout<<"-1\n";
        return ;
    }
    for(auto x:ma)
        if(x.second==1)
        {
            cout<<"-1\n";
            return ;
        }
    int tot=1;
    for(auto x:ma)
    {
        int st=tot;
        for(int j=1;j<x.second;j++)
        {
            tot++;
            cout<<tot<<" ";
        }
        tot++;
        cout<<st<<" ";
    }
    cout<<"\n";
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

C. Sum of Substrings

给你一个01串.计算贡献的方式是遍历第一位到字符串倒数第二位,计算此为和它下一位的数字组成的十进制数的和,即为贡献.每次我们可以把某一位的字符和相邻位字符交换,可交换k次,问k次交换之内,可以得到的最小贡献.

思路:其实很简单,多美居几种情况之后,就会发现,只有当最后一位或者第一位没有1,再把其他地方的1移过来才能让贡献减小.所以针对这两种情况分类讨论,求最小值即可.

#include<map>
#include<cmath>
#include<set>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
string s;
void solve()
{
    int sum=0,n,k,st=-1,en=-1;
    scanf("%lld%lld",&n,&k);
    cin>>s;
    for(int i=s.size()-1;i>=0;i--)
        if(s[i]=='1')
        {
            en=i;
            break;
        }
    for(int i=0;i<s.size();i++)
        if(s[i]=='1')
        {
            st=i;
            break;
        }
    for(int i=1;i<s.size();i++)
    {
        sum+=(s[i-1]-'0')*10+s[i]-'0';
    }
    if(en==-1&&st==-1)
    {
        cout<<sum<<"\n";
        return ;
    }
    else if(en==st&&en!=-1)
    {
        if(k>=s.size()-1-en)
        {
            cout<<min(sum,(int)1)<<"\n";
            return ;
        }
        else if(k>=st)
        {
            cout<<min(sum,(int)10)<<"\n";
            return ;
        }
        else
        {
            cout<<sum<<"\n";
            return ;
        }
    }
    else
    {
        if(k>=s.size()-1-en&&en!=s.size()-1)
        {
            k-=(s.size()-1-en);
            sum-=10;
        }
        if(k>=st&&st!=0)
        {
            k-=st;
            sum--;
        }
        cout<<sum<<"\n";
        return ;
    }
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

D. Max GEQ Sum

题意:题目给你一个数组,问你该数组的所有子区间是否满足该子区间的最大值大于或者等于该区间值的和.

思路:首先看题,可知我们要维护的是一个区间前缀和的最大值,最小值..针对于数组的每个值,我们去贪心的寻找到以该值最为最大值的情况下区间值的和最大的情况.因为当这个数字作为区间最大值时,只要连包含该数字的区间和的最大值都小于该数字,那么肯定成立.那么我们就枚举数组的每个值的区间来判断.

如何找到这个特殊的,以该数字作为最大值且区间和最大的情况呢.可以采用单调栈的方式,去求的每个数左边和右边第一个比它大的数字的位置这两个位置(不包含端点)存在一个区间是最大值,因为要使该数字为最大值,区间内就不能出现更大的.所以我们在该数字右边寻找在区间内的前缀和最大值,在左边寻找前缀和最小值(因为要包含这个数,所以要再亮边找).用有短的最大值减去左端的最小值,即为最大的区间的和.再将这个值与原数比较即可.

#include<map>
#include<cmath>
#include<set>
#include<stack>
#include<queue>
#include<string>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<unordered_set>
#include<unordered_map>
#define int long long
using namespace std;
const int N =5e5+10,mod=998244353;
struct node
{
    int l,r;
    int maxx,minn;
}tr[800005];
int arr[200005],sum[200005];
int lmax[200005],rmax[200005];
void build(int node ,int l,int r)
{
    tr[node].l=l,tr[node].r=r;
    if(l==r)
    {
        tr[node].maxx=sum[l];
        tr[node].minn=sum[l];
        return;
    }
    int mid=(l+r)/2;
    int L=node<<1,R=(node<<1)+1;
    build(L,l,mid);
    build(R,mid+1,r);
    tr[node].maxx=max(tr[L].maxx,tr[R].maxx);
    tr[node].minn=min(tr[L].minn,tr[R].minn);
    return ;
}
int query1(int node,int l,int r)
{
    if(l<=tr[node].l&&tr[node].r<=r)
        return tr[node].maxx;
    int mid=(tr[node].l+tr[node].r)/2;
    int L=node<<1,R=(node<<1)+1;
    int maxx=-1e9;
    if(l<=mid)maxx=max(maxx,query1(L,l,r));
    if(r>mid)maxx=max(maxx,query1(R,l,r));
    return maxx;
}
int query2(int node,int l,int r)
{
    if(l<=tr[node].l&&tr[node].r<=r)
        return tr[node].minn;
    int mid=(tr[node].l+tr[node].r)/2;
    int L=node<<1,R=(node<<1)+1;
    int maxx=1e18;
    if(l<=mid)maxx=min(maxx,query2(L,l,r));
    if(r>mid)maxx=min(maxx,query2(R,l,r));
    return maxx;
}

/*
线段树维护的是前缀和的最大值和最小值
*/
stack<int>st;
void solve()
{
    arr[0]=1e9+7;    
    int n;
    scanf("%lld",&n);
    arr[n+1]=1e9+7;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&arr[i]);
        sum[i]=sum[i-1]+arr[i];
    }
    build(1,0,n);
    while(st.size())
        st.pop();
    st.push(0);
    for(int i=1;i<=n;i++)
    {
        while(arr[st.top()]<=arr[i])
            st.pop();
        lmax[i]=st.top();
        st.push(i);
    }
//向右跑,用单调栈找到每个数右边第一个大于它的数
    while(st.size())
        st.pop();
    st.push(n+1);
    for(int i=n;i>=1;i--)
    {
        while(arr[st.top()]<=arr[i])
            st.pop();
        rmax[i]=st.top();
        st.push(i);
    }
//向左跑,用单调栈找到每个数左边第一个大于它的数
    while (st.size())
        st.pop();
    for(int i=1;i<=n;i++)
    {
        if(query1(1,i,rmax[i]-1)-query2(1,lmax[i],i-1)>arr[i])
        {
去最大区间和和该数字比较进行判断
            printf("NO\n");
            return ;
        }
    }
    printf("YES\n");
    return ;
}
signed main()
{
    int t;
    cin>>t;
    while(t--)
       solve();
    return 0;
}

加油!

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2022-06-06 17:30:41  更:2022-06-06 17:31:33 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 1:35:31-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码