Codeforces Global Round 3

Codeforces Global Round 3

A. Another One Bites The Dust

有若干个a,有若干个b,有若干个ab。你现在要把这些串拼成一个串,使得任意两个相邻的位置都是不同字符,求可能的最长串长度。

枚举一下\(a\)开头还是\(b\)开头,那么接下来就被唯一确定了。

#include<iostream>
#include<cstdio>
using namespace std;
int a,b,c;long long ans;
int main()
{
    scanf("%d%d%d",&a,&b,&c);
    ans=0ll+c*2+min(a,b+1)+min(a,b);
    if(b)--b,ans=max(ans,1ll+c*2+min(a,b+1)+min(a,b));
    printf("%lld\n",ans);
    return 0;
}

B. Born This Way

\(n\)个航班从\(A\)前往\(B\),起飞时间分别是\(a_1,a_2,...,a_n\),飞行时间都是\(t_a\)。有\(m\)个航班从\(B\)前往\(C\),起飞时间分别是\(b_1,b_2,...,b_m\),飞行时间是\(t_b\)。现在有一个人要从\(A\)\(C\),你可以取消不超过\(k\)个航班,使得这个人到达\(C\)的时间最晚。
求出最晚时间,如果可以让这个人无法到达,输出\(-1\)

显然这个人越早到达\(B\)越好,所以我们取消掉的一定是\(a\)的一段前缀。而到达\(B\)之后一定会坐上最早出发的航班,所以同理删去到达之后的一段连续的航班。
那么枚举一下在\(a\)删掉的前缀长度就行了。
注意判断一下\(n\le k,m\le k\)的情况

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 200200
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,m,ta,tb,k,ans;
int a[MAX],b[MAX];
int main()
{
    n=read();m=read();ta=read();tb=read();k=read();
    for(int i=1;i<=n;++i)a[i]=read();
    for(int i=1;i<=m;++i)b[i]=read();
    if(n<=k||m<=k){puts("-1");return 0;}
    for(int i=0,p=1;i<=n&&i<=k;++i)
    {
        while(p<=m&&b[p]<a[i+1]+ta)++p;
        if(m-p+1+i<=k){puts("-1");return 0;}
        ans=max(ans,b[p+k-i]+tb);
    }
    printf("%d\n",ans);
    return 0;
}

C. Crazy Diamond

你有一个长度为\(n\)的一个排列\(p\),其中\(n\)是一个偶数。
你的任务是要把这个排列排序,两个位置可以交换当前仅当满足\(2|i-j|\ge n\)
你需要构造一个交换次数不超过\(5n\)的交换方式。

考虑顺次把每个数归位的过程。
分情况讨论一下,假设当前第\(i\)个数在位置\(p\)
如果\(p,i\)两个位置可以直接交换,那么就直接交换。
否则如果\(p,i\)都可以和\(1\)交换,那么通过\(1\)进行交换就行。
否则如果\(p,i\)都可以和\(n\)交换,那么通过\(n\)进行交换就行。
否则\(p\)可以和\(1\)\(i\)可以和\(n\)交换,那么通过\((p,1),(i,n),(1,n),(p,1),(i,n)\)这样\(5\)次操作就可以交换。
所以最坏情况下就是\(5n\)次。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
#define MAX 300300
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,p[MAX],b[MAX];
bool chk(int i,int j){return 2*abs(i-j)>=n;}
vector<pair<int,int> > Ans;
void add(int i,int j){if(i==j)return;swap(p[i],p[j]);b[p[i]]=i;b[p[j]]=j;Ans.push_back(make_pair(i,j));}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)b[p[i]=read()]=i;
    for(int i=1;i<=n;++i)
    {
        if(i==b[i])continue;
        if(chk(b[i],i))add(i,b[i]);
        else
        {
            int p=b[i];
            if(chk(1,p)&&chk(1,i))add(1,p),add(1,i),add(1,p);
            else if(chk(n,i)&&chk(p,n))add(n,i),add(p,n),add(n,i);
            else if(chk(1,p)&&chk(i,n))add(1,p),add(i,n),add(1,n),add(1,p),add(i,n);
        }
    }
    printf("%d\n",(int)Ans.size());
    for(auto p:Ans)printf("%d %d\n",p.first,p.second);
    return 0;
}

D. Dirty Deeds Done Dirt Cheap

给定两个长度为\(n\)的数列\(a,b\),保证所有数都在\([1,2n]\)中且各不相同。
现在你要选出尽可能多的在\([1,n]\)的数,使他们构成一个数列\(\{i\}\),满足数列:
\(a_{i1}b_{i1}a_{i2}b_{i2}...a_{im}b_{im}\)是一个波动序列。
即每个数都同时大于相邻的两个数或者小于相邻的两个数。

首先数列有两种形式,第一种是\(<><><>\)这样子,第二种是\(><><><\)在这样子。
那么这样子就确定了\((a_i,b_i)\)组内的大小关系,可以把二元组分成两类,两类只能分别构造答案。
那么一个二元组可以连在另外一个二元组前面,当前仅当\(b_i<a_j\)或者\(b_i>a_j\)
假如我们只考虑\(b_i<a_j\)的情况。考虑把所有数按照\(a_i\)排序,这样子每个二元组的出边就是一个后缀,那么我们只需要贪心的把边连到\(b\)最小的上面去就行了,这样子拿线段树就可以维护了,或者进一步,发现\(b\)是单增的,所以用堆之类的东西维护就行了。
然而这样子很呆。
我们换一种考虑的方法,因为\(b\)是单增的,所以我们直接按照\(b\)排序,此时发现按照排序之后的结果就是合法的。
因为\(a_{i}>b_{i}<b_{i+1},a_{i+1}>b_{i+1}\)
所以有\(a_{i}>b_{i}<a_{i+1}>b_{i+1}\)
类似的,反过来\(b_i>a_j\)按照\(a\)排序就行了。

#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAX 300300
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,r,a[MAX],b[MAX],p[MAX];
bool cmpb(int x,int y){return b[x]<b[y];}
bool cmpa(int x,int y){return a[x]<a[y];}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)a[i]=read(),b[i]=read(),r+=a[i]>b[i],p[i]=i;
    printf("%d\n",max(r,n-r));
    if(r>n-r)
    {
        sort(&p[1],&p[n+1],cmpb);
        for(int i=1;i<=n;++i)
            if(a[p[i]]>b[p[i]])printf("%d ",p[i]);
    }
    else
    {
        sort(&p[1],&p[n+1],cmpa);
        for(int i=n;i;--i)
            if(a[p[i]]<b[p[i]])printf("%d ",p[i]);
    }
    puts("");
    return 0;
}

E. Earth Wind and Fire

数轴上有\(n\)个石头,一开始时第\(i\)个石头在位置\(s_i\),每次你可以选择两个石头\(i,j\),满足\(s_i<s_j\),然后选择一个\(d\),满足\(2d\le |s_i-s_j|\),然后把\(i\)移动到\(s_i+d\)位置,\(j\)移动到\(s_j-d\)位置。
给定一个长度为\(n\)的数列\(t\),表示最终在\(t_i\)位置要有一个石头。
问能否满足条件。
如果可以构建一个方案。

不难发现如果合法我们一定可以不改变相对顺序。
那么起始位置和目标位置做差之后,如果是要向右移动,那么我们直接压进栈里面。
否则从栈顶取元素进行移动。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define MAX 300300
#define mp make_pair
inline int read()
{
    int x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,t[MAX],f;
pair<int,int> s[MAX],Q[MAX];
vector<pair<pair<int,int>,int> >Ans;
void add(int i,int j,int d)
{
    i=s[i].second,j=s[j].second;
    Ans.push_back(mp(mp(i,j),d));
}
int main()
{
    n=read();
    for(int i=1;i<=n;++i)s[i]=make_pair(read(),i);
    for(int i=1;i<=n;++i)t[i]=read();
    sort(&t[1],&t[n+1]);sort(&s[1],&s[n+1]);
    for(int i=1;i<=n;++i)
        if(s[i].first<t[i])
            Q[++f]=mp(i,t[i]-s[i].first);
        else
        {
            if(s[i].first==t[i])continue;
            int p=s[i].first-t[i];
            while(p&&f)
            {
                int mv=min(p,Q[f].second);
                add(Q[f].first,i,mv);
                p-=mv;Q[f].second-=mv;
                if(!Q[f].second)--f;
            }
            if(p){puts("NO");return 0;}
        }
    if(f){puts("NO");return 0;}
    puts("YES");
    printf("%d\n",(int)Ans.size());
    for(auto p:Ans)printf("%d %d %d\n",p.first.first,p.first.second,p.second);
    return 0;
}

F. Foo Fighters

你有\(n\)个物品,每个物品有两个权值\(val\)\(mask\)
你可以选择一个数\(s\),然后修改所有数的\(val\),如果\(val\& mask\)有奇数个\(1\)就把\(val\)变成\(-val\)
输出一个\(s\),使得权值和符号变反。

显然可以把所有位分开考虑,如果选择了这一位并且这一位的\(mask\)上有\(1\)就可以直接取反。
现在的问题变成了我们要选择哪些位置。
首先位与位之间是么有顺序关系的,所以我们随意用什么顺序考虑都是可行的,不妨从高位往低位处理。
我们用类似归纳法的思想来考虑,我们先不妨令数字和是正数(如果是负数可以把所有东西全部取反)
如果我们已经处理完了若干位,如果已经让数字和变成了负数,那么结束了。
否则的话,考虑是否改变这一位上的所有值,但是如果只考虑位的话如果这一位选了会影响后面的选择,所以不能直接这样贪心。
我们钦定每个数的正负只在其最低位的时候考虑,因为这些数如果在这一位不改就不能再改了,所以每个数就只会被考虑一次。那么如果以这一位为最低位的数的权值和为正数,那么直接取反就行了。
至于为啥是对的。。。emmm,窝感觉很对QwQ。

#include<iostream>
#include<cstdio>
using namespace std;
#define ll long long
#define MAX 300300
inline ll read()
{
    ll x=0;bool t=false;char ch=getchar();
    while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    if(ch=='-')t=true,ch=getchar();
    while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    return t?-x:x;
}
int n,v[MAX];
ll a[MAX],s,sum;
int main()
{
    n=read();
    for(int i=1;i<=n;++i)v[i]=read(),a[i]=read(),sum+=v[i];
    if(sum<0)for(int i=1;i<=n;++i)v[i]=-v[i];
    for(int i=62;~i;--i)
    {
        ll ss=0;
        for(int j=1;j<=n;++j)if(a[j]==(1ll<<i))ss+=v[j];
        if(ss>0)s|=1ll<<i;
        for(int j=1;j<=n;++j)
            if(a[j]&(1ll<<i))
            {
                a[j]^=1ll<<i;
                if(ss>0)v[j]=-v[j];
            }
    }
    printf("%lld\n",s);
    return 0;
}

G. Gold Experience

\(n\)个点,每个点有一个点权\(a_i\),如果两个点权的\(gcd>1\),那么他们之间就会连上一条边。
定义一个集合中的一个点是好的,当前仅当这个点和点集中其他所有点都有连边。
你要找到一个大小为\(k\)的点集,满足其中所有点都是好的或者所有点都是不好的。

咕咕咕咕

H. Holy Diver

咕咕咕

转载于:https://www.cnblogs.com/cjyyb/p/10984063.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
东南亚位于我国倡导推进的“一带一路”海陆交汇地带,作为当今全球发展最为迅速的地区之一,近年来区域内生产总值实现了显著且稳定的增长。根据东盟主要经济体公布的最新数据,印度尼西亚2023年国内生产总值(GDP)增长5.05%;越南2023年经济增长5.05%;马来西亚2023年经济增速为3.7%;泰国2023年经济增长1.9%;新加坡2023年经济增长1.1%;柬埔寨2023年经济增速预计为5.6%。 东盟国家在“一带一路”沿线国家中的总体GDP经济规模、贸易总额与国外直接投资均为最大,因此有着举足轻重的地位和作用。当前,东盟与中国已互相成为双方最大的交易伙伴。中国-东盟贸易总额已从2013年的443亿元增长至 2023年合计超逾6.4万亿元,占中国外贸总值的15.4%。在过去20余年中,东盟国家不断在全球多变的格局里面临挑战并寻求机遇。2023东盟国家主要经济体受到国内消费、国外投资、货币政策、旅游业复苏、和大宗商品出口价企稳等方面的提振,经济显现出稳步增长态势和强韧性的潜能。 本调研报告旨在深度挖掘东南亚市场的增长潜力与发展机会,分析东南亚市场竞争态势、销售模式、客户偏好、整体市场营商环境,为国内企业出海开展业务提供客观参考意见。 本文核心内容: 市场空间:全球行业市场空间、东南亚市场发展空间。 竞争态势:全球份额,东南亚市场企业份额。 销售模式:东南亚市场销售模式、本地代理商 客户情况:东南亚本地客户及偏好分析 营商环境:东南亚营商环境分析 本文纳入的企业包括国外及印尼本土企业,以及相关上下游企业等,部分名单 QYResearch是全球知名的大型咨询公司,行业涵盖各高科技行业产业链细分市场,横跨如半导体产业链(半导体设备及零部件、半导体材料、集成电路、制造、封测、分立器件、传感器、光电器件)、光伏产业链(设备、硅料/硅片、电池片、组件、辅料支架、逆变器、电站终端)、新能源汽车产业链(动力电池及材料、电驱电控、汽车半导体/电子、整车、充电桩)、通信产业链(通信系统设备、终端设备、电子元器件、射频前端、光模块、4G/5G/6G、宽带、IoT、数字经济、AI)、先进材料产业链(金属材料、高分子材料、陶瓷材料、纳米材料等)、机械制造产业链(数控机床、工程机械、电气机械、3C自动化、工业机器人、激光、工控、无人机)、食品药品、医疗器械、农业等。邮箱:market@qyresearch.com

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值