所有的题目都可以在CodeForces上查看

中间看起来有很多场比赛我没有写了

其实是因为有题目没改完

因为我不想改,所以就没有写了(大部分题目还是改完了的)

我还是觉得如果是打了的比赛就一场一场写比较好

要不然以后就写有难度的、比较好的题目??


这场比赛时间真心良心(只是没吃饭)

状态也很好,考场上把\(ABCDE\)切了

\(F\)是自己弃疗了。。。

不管啦不管啦,进入正题了

题解

A.Points on the line

翻译:

给定一个长度为\(n\)的数组

问最少删去几个数之后使得最大值减最小值的结果小于等于\(d\)

题解

考虑\(n\)的范围很小

排序之后枚举每一段区间,计算答案即可

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int a[200],n,D;
int main()
{
n=read();D=read();
for(int i=1;i<=n;++i)a[i]=read();
sort(&a[1],&a[n+1]);
int ans=0;
for(int i=n;i;--i)
{
ans++;
for(int j=1;j+i-1<=n;++j)
if(a[j+i-1]-a[j]<=D)
{
cout<<ans-1<<endl;
return 0;
}
} }

B.Our Tanya is Crying Out Loud

翻译

给定\(n,k,A,B\),

一开始\(x=n\),

每次可以花费\(A\)的代价

使得\(x=x-1\) ,

每次可以花费\(B\)的代价

使得\(x=x/k\)(前提是\(x\%k=0\))

问使得\(x\)变成\(0\)的最小代价

题解

每次贪心的考虑把\(x\)变成\([\frac{x}{k}]\)的代价

看看是一个个减更优还是先减再除更优

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
ll n,K,A,B;
int main()
{
n=read();K=read();A=read();B=read();
ll ans=0;
if(n<K){ans=A*(n-1);cout<<ans<<endl;return 0;}
if(K==1){ans=A*(n-1);cout<<ans<<endl;return 0;}
while(n!=1)
{
if(n<K)
{
ans+=A*(n-1);
cout<<ans<<endl;
return 0;
}
ll gg=n/K;
ll t1=(n-gg)*A;
ll t2=(n%K)*A+B;
ans+=min(t1,t2);
n=gg;
}
cout<<ans<<endl;
return 0;
}

C.Phone Numbers

翻译

给定一个长度为\(n\)的串\(S\)

要求只能用\(n\)中包含的字符构建一个长度为\(k\)的字符串\(T\)

使得\(T\)的字典序最小,并且\(S\)的字典序小于\(T\)

题解

如果\(k>n\)直接把\(S\)复制一遍

后面填字典序最小的字符就行了

否则的话,把两个字符串从首位开始对齐

从\(T\)的末尾开始填

只要\(S\)的当前位置不是字典序最大的字符

就填上比它大的字符

然后前面直接复制

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
int n,k;
char ch[120000];
int ans[120000];
int g[120000];
int main()
{
cin>>n>>k;
scanf("%s",ch+1);
for(int i=1;i<=n;++i)g[i]=ch[i]-96;
sort(&g[1],&g[n+1]);
int t=unique(&g[1],&g[n+1])-g-1;
if(k>n)
{
for(int i=1;i<=n;++i)putchar(ch[i]);
for(int i=n+1;i<=k;++i)putchar(g[1]+96);
puts("");
return 0;
}
bool fl=false;
for(int i=k;i;--i)
{
int c=ch[i]-96;
if(fl){ans[i]=c;continue;}
if(c==g[t])ans[i]=g[1];
else
{
ans[i]=g[lower_bound(&g[1],&g[t+1],c)-g+1];
fl=true;
}
}
for(int i=1;i<=k;++i)putchar(ans[i]+96);
puts("");
return 0;
}

D.Alena And The Heater

翻译

很难翻译呀,配着英文看还是挺好的

给定你一个数列\(A\)

以及让你构造的\(01\)串\(B\)

满足以下条件:

\(b[1]=b[2]=b[3]=b[4]=0\)

\(b[i]=1\),当满足:

\[a_i, a_{i - 1}, a_{i - 2}, a_{i - 3}, a_{i - 4} >r \ and\ b_{i - 1} = b_{i - 2} = b_{i - 3} = b_{i - 4} = 1
\]

\(b[i]=0\),当满足:

\[a_i, a_{i - 1}, a_{i - 2}, a_{i - 3}, a_{i - 4} <l \ and\ b_{i - 1} = b_{i - 2} = b_{i - 3} = b_{i - 4} = 0
\]

如果都不满足上面的两种情况

那么\(b[i]=b[i-1]\)

保证题目有解

输出能够构造出\(B'\)的\(l,r\)

题解

这题的关键在哪里?

保证题目有解

所以每次只需要找到\(01\)变化的地方

相应的对\(l/r\)取一个\(max/min\)

很简单吧

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 120000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,a[MAX],b[MAX],bb[MAX];
char ch[MAX];
int p[MAX],pp[MAX];
int q[MAX];
int main()
{
n=read();
for(int i=1;i<=n;++i)a[i]=read();
scanf("%s",ch+1);
for(int i=1;i<=n;++i)bb[i]=ch[i]-48;
for(int i=5;i<=n;++i)
{
p[i]=min(a[i],a[i-1]);
p[i]=min(p[i],a[i-2]);
p[i]=min(p[i],a[i-3]);
p[i]=min(p[i],a[i-4]);
}
for(int i=5;i<=n;++i)
{
q[i]=max(a[i],a[i-1]);
q[i]=max(q[i],a[i-2]);
q[i]=max(q[i],a[i-3]);
q[i]=max(q[i],a[i-4]);
} for(int i=4;i<=n;++i)
{
if(b[i]==b[i-1]&&b[i]==b[i-2]&&b[i]==b[i-3])
pp[i]=b[i];
else pp[i]=2;
} int l=-1e9,r=1e9,now=0;
for(int i=5;i<=n;++i)
{
if(bb[i]!=bb[i-1])
{
if(bb[i]==1)l=max(l,q[i]+1);
else r=min(r,p[i]-1);
}
}
cout<<l<<' '<<r<<endl;
return 0;
}

E. Cashback

翻译

给定长度为\(n\)的序列\(a\),以及一个\(k\)

你可以把他划分成若干段

设某一段的长度为\(len\)

那么,这一段就会删去\([\frac{len}{k}]\)个最小的数

求出这个序列能够划分出的最小和

题解

\(O(n^2)\)的\(dp\)是很显然的

\[f[i]=min(f[j]+Calc(j+1,i))
\]

\(Calc\)貌似要用主席树?,

复杂度还要套个\(log\)

但是,我们真的有必要这么做吗?

仔细观察分段

如果我们分出一个长度为\(2k\)的段

似乎不会比分成两段长度为\(k\)的更优

因为两段\(k\)中是分别删去最小值

而一段\(2k\)中删去的是最小的两个值

所以,我们就可以知道分段的时候长度分成\(k\)

而不是更多的连续在一起的值

那么,分成\(k+p(p<k)\)有没有意义呢?

数字越多,最小值是单调递减的

那么,分成这样的一组不会比分出一段\(k\)更优

而分出一段\(p\)

等价于分出\(p\)个\(1\)

所以,其实我们的转移没有必要\(O(n)\)来做

只需要考虑是分出一段\(k\)

还是分出一个\(1\)就行了

每次分出一段\(k\)就要删去一个数

所以要查找区间最小值

用\(ST\)表就行了

时间复杂度\(O(nlog)\)

我因为一开始写了主席树,索性用主席树算的答案

复杂度不变,\(O(nlog)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 120000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
int n,a[MAX],rt[MAX],S[MAX],tt;
ll s[MAX];
ll f[MAX];
int tot,c;
struct Node
{
int ls,rs;
ll sum;
int size;
}t[MAX<<5];
void Modify(int &now,int ff,int l,int r,int p,int w)
{
now=++tot;
t[now]=t[ff];t[now].size++;t[now].sum+=1ll*S[p]*w;
if(l==r)return;
int mid=(l+r)>>1;
if(p<=mid)Modify(t[now].ls,t[ff].ls,l,mid,p,w);
else Modify(t[now].rs,t[ff].rs,mid+1,r,p,w);
}
ll Query(int r1,int r2,int l,int r,int K)
{
if(l==r){return K*S[l];}
int mid=(l+r)>>1;
int ss=t[t[r2].ls].size-t[t[r1].ls].size;
if(K<=ss)return Query(t[r1].ls,t[r2].ls,l,mid,K);
else return t[t[r2].ls].sum-t[t[r1].ls].sum+Query(t[r1].rs,t[r2].rs,mid+1,r,K-ss);
}
int main()
{
n=read();c=read();
for(int i=1;i<=n;++i)S[++tt]=a[i]=read();
for(int i=1;i<=n;++i)s[i]=s[i-1]+a[i];
sort(&S[1],&S[n+1]);
tt=unique(&S[1],&S[tt+1])-S-1;
for(int i=1;i<=n;++i)
{
int p=lower_bound(&S[1],&S[tt+1],a[i])-S;
Modify(rt[i],rt[i-1],1,tt,p,1);
}
for(int i=1;i<c;++i)f[i]=s[i];
for(int i=c;i<=n;++i)
{
f[i]=f[i-1]+a[i];
ll gg=s[i]-s[i-c]-Query(rt[i-c],rt[i],1,tt,1);
f[i]=min(f[i],gg+f[i-c]);
}
cout<<f[n]<<endl;
return 0;
}

F. Machine Learning

翻译

给定一个长度为\(n\)的序列\(a\)

两种操作

1.询问\([l,r]\)区间内,所有数字出现次数的\(mex\)值

2.将\(p\)位置修改为\(x\)

其中\(mex\)表示的是最小的没有出现过的正整数

题解

很明显的莫队,带修改莫队

离线读入

离散之后维护每个数字出现的次数

其实没有必要对这个值进行类似于直接求\(mex\)的分块

因为出现次数在最坏情况下是\(1,2,3....\)

这个的和是平方级别的

所以\(mex\)一定是根号级别的

这样的话复杂就是对的了

但是细节很多

否则时间挂烂(比如我调了1个多小时)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ll long long
#define RG register
#define MAX 200000
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
struct Event
{
int id;
int l,r,blk;
int lst;
}Q[MAX],P[MAX];
int ans[MAX];
int S[MAX<<1],ss,n,m,a[MAX],b[MAX],blk=3000,tot,q;
int sum[MAX],Sum[MAX];
int Blk[MAX];
bool cmp(Event a,Event b){
if(a.blk!=b.blk) return a.blk<b.blk;
if((a.r-1)/blk!=(b.r-1)/blk)return (a.r-1)/blk<(b.r-1)/blk;
return a.lst<b.lst;
}
void Change(int num,int w)
{
Sum[sum[num]]--;
if(Sum[sum[num]]==0)Blk[(Sum[sum[num]]-1)/500]--;
sum[num]+=w;
Sum[sum[num]]++;
if(Sum[sum[num]]==1)Blk[(Sum[sum[num]]-1)/500]++;
}
int GetAns()
{
for(int i=0;;++i)
{
if(Blk[i]==blk)continue;
for(int j=1;j<=blk;++j)
if(!Sum[i*blk+j])return i*blk+j;
}
}
void Modify(int st,int now,int l,int r)
{
if(st==now)return;
if(now<st)
for(int i=now+1;i<=st;++i)
{
a[P[i].l]=P[i].r;
if(P[i].l>=l&&P[i].l<=r)
{
Change(P[i].lst,-1);
Change(P[i].r,1);
}
}
else
for(int i=now;i>st;--i)
{
a[P[i].l]=P[i].lst;
if(P[i].l>=l&&P[i].l<=r)
{
Change(P[i].r,-1);
Change(P[i].lst,1);
}
}
}
void Work(int pos,int w)
{
Change(a[pos],w);
}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i)b[i]=a[i]=read(),S[++ss]=a[i];
for(int i=1;i<=m;++i)
{
int opt=read(),l=read(),r=read();
if(opt==1){Q[++q]=(Event){q,l,r,(l-1)/blk,tot};}
else
{
P[++tot]=(Event){tot,l,r,0,b[l]};
b[l]=r;
S[++ss]=r;
}
} sort(&S[1],&S[ss+1]);
ss=unique(&S[1],&S[ss+1])-S-1;
for(int i=1;i<=n;++i)a[i]=lower_bound(&S[1],&S[ss+1],a[i])-S;
for(int i=1;i<=tot;++i)
{
P[i].r=lower_bound(&S[1],&S[ss+1],P[i].r)-S;
P[i].lst=lower_bound(&S[1],&S[ss+1],P[i].lst)-S;
}
sort(&Q[1],&Q[q+1],cmp); int md=0,l=1,r=0;
for(int i=1;i<=q;++i)
{
while(r<Q[i].r)Work(++r,1);
while(l>Q[i].l)Work(--l,1);
while(r>Q[i].r)Work(r--,-1);
while(l<Q[i].l)Work(l++,-1);
Modify(Q[i].lst,md,l,r);
md=Q[i].lst;
ans[Q[i].id]=GetAns();
}
for(int i=1;i<=q;++i)
printf("%d\n",ans[i]);
return 0;
}

Codeforces Round #466 (Div. 2)的更多相关文章

  1. Codeforces Round #466 (Div. 2) E. Cashback

    Codeforces Round #466 (Div. 2) E. Cashback(dp + 贪心) 题意: 给一个长度为\(n\)的序列\(a_i\),给出一个整数\(c\) 定义序列中一段长度为 ...

  2. Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F

    Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...

  3. Codeforces Round #466 (Div. 2) -A. Points on the line

    2018-02-25 http://codeforces.com/contest/940/problem/A A. Points on the line time limit per test 1 s ...

  4. Codeforces Round #466 (Div. 2) Solution

    从这里开始 题目列表 小结 Problem A Points on the line Problem B Our Tanya is Crying Out Loud Problem C Phone Nu ...

  5. Codeforces Round #466 (Div. 2) A. Points on the line[数轴上有n个点,问最少去掉多少个点才能使剩下的点的最大距离为不超过k。]

    A. Points on the line time limit per test 1 second memory limit per test 256 megabytes input standar ...

  6. Codeforces Round #466 (Div. 2) 题解

    人生中第三次\(CF\)... 考试中切了\(A\)~\(E\) \(F\)题会做没时间写 题解 A:Points on the line 题意 给定一个数列,删最小的数,使最大差不大于一个定值 So ...

  7. Codeforces Round #466 (Div. 2) B. Our Tanya is Crying Out Loud[将n变为1,有两种方式,求最小花费/贪心]

    B. Our Tanya is Crying Out Loud time limit per test 1 second memory limit per test 256 megabytes inp ...

  8. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  9. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

随机推荐

  1. centos-安装python3.6环境并配置虚拟环境

    python3.6下载地址:https://www.python.org/ftp/python/3.6.4/Python-3.6.4.tgz linux下python环境配置 统一目录: 源码存放位置 ...

  2. Nginx 静态资源缓存设置

    在开发调试web的时候,经常会碰到因浏览器缓存(cache)而经常要去清空缓存或者强制刷新来测试的烦恼,提供下apache不缓存配置和nginx不缓存配置的设置.在常用的缓存设置里面有两种方式,都是使 ...

  3. solr6.6教程-从mysql数据库中导入数据(三)

    整理多半天的solr6.6,终于算是把solr6.6中配置数据库弄出来了,网上的文章千篇一律,各说个的,没有一篇统一覆盖solr6.6版本配置的 帖子,本章节我会把配置的一些注意事项一一列举,由于时间 ...

  4. SVN高级

    #查找有关svn关键字的目录及文件 find / -name "*svn*" find / -name "*Svn*" find / -name "* ...

  5. CentOS常用命令搜集

    centos是32或者64位:getconf LONG_BIT

  6. nyoj135 取石子(二) Nimm博弈

    思路:计算每堆石子的SG值,然后异或得到总的SG值,如果SG=0则输,否则赢. 每堆石子的SG值等于m%(n+1),可以自己推算一下. AC代码 #include <cstdio> #in ...

  7. 安装linux环境及相关包方法

    安装linux系统: 先下载 iso镜像文件,在windows系统下,插入u盘,下载 Ultraiso软件,安装好后,根据 http://jingyan.baidu.com/article/a378c ...

  8. Zookeeper笔记3——原理及其安装使用

    Zookeeper到底能干什么? 1.配置管理:这个好理解.分布式系统都有好多机器,Zookeeper提供了这样的一种服务:一种集中管理配置的方法,我们在这个集中的地方修改了配置,所有对这个配置感兴趣 ...

  9. R︱shiny实现交互式界面布置与搭建(案例讲解+学习笔记)

    要学的东西太多,无笔记不能学~~ 欢迎关注公众号,一起分享学习笔记,记录每一颗"贝壳"~ --------------------------- 看了看往期的博客,这个话题竟然是第 ...

  10. 微信 Tinker 的一切都在这里,包括源码

    最近半年以来,Android热补丁技术热潮继续爆发,各大公司相继推出自己的开源框架.Tinker在最近也顺利完成了公司的审核,并非常荣幸的成为github.com/Tencent上第一个正式公开的项目 ...