Codeforces Round #542 (Div. 1) 题解
开学了住校了打不了深夜场
好难受啊QwQ
A
显然对于每个起点,我们只需要贪心记录这个起点出发出去的糖果数量以及离自己最近的糖果
因为这个起点最后一次装载糖果一定是装载终点离自己最近的那个糖果
$ O(n^2)$暴力贪心即可
有线性做法懒得写了
- #include<ctime>
- #include<cmath>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<vector>
- #define rt register int
- #define ll long long
- using namespace std;
- inline ll read(){
- ll x=;char zf=;char ch=getchar();
- while(ch!='-'&&!isdigit(ch))ch=getchar();
- if(ch=='-')zf=-,ch=getchar();
- while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
- }
- void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
- void writeln(const ll y){write(y);putchar('\n');}
- int k,m,n,x,y,z,cnt,ans;
- int sum[],far[];
- int main(){
- n=read();m=read();
- for(rt i=;i<=m;i++){
- x=read();y=read();
- sum[x]++;
- if((y+n-x)%n<far[x]||sum[x]==)far[x]=(y+n-x)%n;
- }
- for(rt i=;i<=n;i++){
- int ans=;
- for(rt j=;j<=n;j++)ans=max(ans,(sum[j]-)*n+far[j]+(j+n-i)%n);
- write(ans),putchar(' ');
- }
- return ;
- }
B
构造题的做法很多样化
一开始写了一个乱七八糟的乱搞过了
然后看了眼标程提供的Answer顿感智商被碾压
我们只需要在最前面放一个$ -1$
后面放一段长度为$ len$,和为$ sum$的非负整数序列即可
则差值为$$(sum-1)(len+1)-sum·len=sum-len-1$$
随便拿个$ len$跑出来一组$sum$即可
我原先做法就不讲了
- #include<ctime>
- #include<cmath>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<vector>
- #define rt register int
- #define ll long long
- using namespace std;
- inline ll read(){
- ll x=;char zf=;char ch=getchar();
- while(ch!='-'&&!isdigit(ch))ch=getchar();
- if(ch=='-')zf=-,ch=getchar();
- while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
- }
- void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
- void writeln(const ll y){write(y);putchar('\n');}
- int k,m,n,x,y,z,cnt,ans;
- void pt(int x,int y){
- for(rt i=;i<=y;i++)if(x<=)cout<<x<<' ',x=;
- else cout<<<<' ',x-=;
- }
- int main(){
- k=read();
- int S=k+,L=;
- cout<<L+<<endl;
- cout<<-<<' ';pt(S,L);
- return ;
- }
C
每次的答案相当于上次的答案加上当前串所有后缀的贡献
那每次把当前串反向插入到$ trie$树中
如果有新建节点就利用这个点往上四层的四个祖先计算$ DP$值并加入答案
注意细节
我的$ trie$树奇丑无比不要模仿....
- #include<ctime>
- #include<cmath>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<vector>
- #define p 1000000007
- #define rt register int
- #define ll long long
- using namespace std;
- inline ll read(){
- ll x=;char zf=;char ch=getchar();
- while(ch!='-'&&!isdigit(ch))ch=getchar();
- if(ch=='-')zf=-,ch=getchar();
- while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
- }
- void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
- void writeln(const ll y){write(y);putchar('\n');}
- int k,m,n,x,y,z,cnt,ans,Root;
- struct trie{
- int son[],fa;
- }a[];
- int v[],dp[];
- void insert(int &x,int pl){
- if(!x)x=++cnt;if(pl==)return;
- bool fla=;int val=;
- if(!a[x].son[v[pl]])a[x].son[v[pl]]=++cnt;a[a[x].son[v[pl]]].fa=x;
- if(!dp[a[x].son[v[pl]]]){
- int now=x,zhi=;
- for(rt i=;i<;i++){
- if(!now)continue;
- zhi|=(<<i)*(v[pl+i]);
- if((zhi==||zhi==||zhi==||zhi==)&&i==)break;
- (val+=dp[now])%=p;now=a[now].fa;
- }
- dp[a[x].son[v[pl]]]=val,(ans+=val)%=p;
- }
- insert(a[x].son[v[pl]],pl-);
- }
- int main(){
- n=read();dp[]=;
- for(rt i=;i<=n;i++){
- v[i]=read();z=i;
- insert(Root,i);
- writeln(ans);
- }
- return ;
- }
D
考虑构造一个新数组v
每当新在末尾增加一个数$a_i$的时候,把$ v_i$设置成1,把上一个值和$ a_i$相同的位置的v改成-1,把上上个值和$ a_i$相同的位置的v改成0
这么做的意义是$ \sum\limits_{j=L}^i v_j$恰好表示了这个后缀中只出现一次的数的数量
则有$ DP$方程:$$ dp_i=\sum_{j=0}^{i-1}dp_j[\sum_{d=j+1}^i v_d \leq k]$$
设$ S_i$表示$ \sum\limits_{j=1}^i v_j$
则有$ DP$方程:$$ dp_i=\sum_{j=1}^{i-1}dp_j(S_j\geq S_i-k)$$
每次求$ dp_i$的时候$ S_i$均可看成一个常数
因此每次相当于求所有$ S_j$不超过某个值的$ dp_j$之和
考虑分块
$ f_{x,y}$表示第$ x$个块,所有$ S$值不超过$ y$的$ dp$值之和
每次对$ S$修改的时候整块的在上面打标记,非整块暴力重构即可
时空复杂度均为$ O(n \sqrt{n})$
代码中为了方便将数组从$ 0$开始编号,与上面略有不同,请稍加注意
- #include<ctime>
- #include<cmath>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<vector>
- #define p 998244353
- #define rt register int
- #define ll long long
- using namespace std;
- inline ll read(){
- ll x=;char zf=;char ch=getchar();
- while(ch!='-'&&!isdigit(ch))ch=getchar();
- if(ch=='-')zf=-,ch=getchar();
- while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
- }
- void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
- void writeln(const ll y){write(y);putchar('\n');}
- int k,m,n,x,y,z,cnt,ans;
- int la[],now[],v[],s[],dp[];
- int f[][],tag[],blo,maxs[],id[];
- void build(int x){
- int Min=,Max=-;
- for(rt i=x*blo;i<(x+)*blo;i++){
- if(s[i]<Min)Min=s[i];
- if(s[i]>Max)Max=s[i];
- }
- maxs[x]=Max-Min;
- for(rt i=;i<=maxs[x];i++)f[x][i]=;
- tag[x]+=Min;
- for(rt i=x*blo;i<(x+)*blo;i++)s[i]-=Min,(f[x][s[i]]+=dp[i])%=p;
- for(rt i=;i<=Max-Min;i++)(f[x][i]+=f[x][i-])%=p;
- }
- void change(int L,int val,int R){
- if(val==v[L])return;
- int upd=val-v[L];v[L]=val;
- if(id[L]==id[R]){
- for(rt i=L;i<=R;i++)s[i]+=upd;
- return;
- }
- for(rt i=L;i<(id[L]+)*blo;i++)s[i]+=upd;build(id[L]);
- for(rt i=id[L]+;;i++){
- if(i==id[R]){
- for(rt j=i*blo;j<=R;j++)s[j]+=upd;
- return;
- }
- tag[i]+=upd;
- }
- }
- int query(int x,int val){
- //块x中大于等于val的值
- val-=tag[x];
- if(val>maxs[x])return ;
- if(val<=)return f[x][maxs[x]];
- return (f[x][maxs[x]]-f[x][val-])%p;
- }
- int main(){
- n=read();k=read();blo=(int)sqrt(n);
- for(rt i=;i<n;i++)id[i]=i/blo;
- for(rt i=;i<=n;i++)now[i]=la[i]=-;
- for(rt i=;i<n;i++){
- x=read();if(i)s[i]=s[i-]+tag[(i-)/blo];
- if(now[x]!=-)change(now[x],-,i);
- if(la[x]!=-)change(la[x],,i);
- la[x]=now[x];now[x]=i;v[i]=;s[i]++;
- for(rt j=;j<=i;j+=blo)(dp[i]+=query(id[j],s[i]+tag[id[i]]-k))%=p;
- for(rt j=i/blo*blo;j<i;j++)if(s[j]+tag[id[j]]>=s[i]+tag[id[i]]-k)(dp[i]+=dp[j])%=p;
- if(s[i]<=k)dp[i]++;
- if((i+)%blo==)build(id[i]);
- }
- cout<<(dp[n-]%p+p)%p;
- return ;
- }
E
很有趣的构造题
钦定一号点为根
首先用$ n-1$次询问得出每个点的$ size$大小
显然$ size$小的点不可能成为$ size$大的点的父亲
按$ size$排序,并按$ size$从小到大判断每个点的孩子编号
思路是将当前所有$ size$比自己小且不是任何点的孩子的节点排成一行
用一个集合维护所有不是任何点的孩子的节点
每次二分找出最靠左的那一个是自己孩子的节点,并将其从集合中删除
最后把自己加入集合即可
复杂度是每个点的孩子数·$\log$即$ O(n·\log n)$的
- #include<ctime>
- #include<cmath>
- #include<cstdio>
- #include<cstring>
- #include<iostream>
- #include<algorithm>
- #include<queue>
- #include<vector>
- #include<set>
- #define flush fflush(stdout)
- #define rt register int
- #define ll long long
- using namespace std;
- inline ll read(){
- ll x=;char zf=;char ch=getchar();
- while(ch!='-'&&!isdigit(ch))ch=getchar();
- if(ch=='-')zf=-,ch=getchar();
- while(isdigit(ch))x=x*+ch-'',ch=getchar();return x*zf;
- }
- void write(ll y){if(y<)putchar('-'),y=-y;if(y>)write(y/);putchar(y%+);}
- void writeln(const ll y){write(y);putchar('\n');}
- int k,m,n,x,y,z,cnt,ans;
- int size[];
- struct node{
- int x,size;
- bool operator <(const node s)const{
- return size<s.size;
- }
- }a[];
- int q[],t;
- set<int>s;
- int erase[],fa[],top;
- bool chk(int L,int R,int nd){
- writeln();writeln();
- writeln(R-L+);
- for(rt i=L;i<=R;i++)write(q[i]),putchar(' ');putchar('\n');
- writeln(nd);flush;
- return read();
- }
- int main(){
- n=read();size[]=n;
- for(rt i=;i<=n;i++){
- writeln();
- writeln();
- writeln(n-);
- for(rt j=;j<=n;j++)write(j),putchar(' ');putchar('\n');
- writeln(i);flush;
- size[i]=read();
- }
- for(rt i=;i<=n;i++)a[i]={i,size[i]};
- sort(a+,a+n+);
- for(rt i=;i<=n;i++){
- t=;
- for(auto i:s)q[++t]=i;
- for(rt lef=;lef<=t;){
- if(!chk(lef,t,a[i].x))break;
- int L=lef,R=t,ans=;
- while(L<=R){
- const int mid=L+R>>;
- if(chk(L,mid,a[i].x))ans=mid,R=mid-;
- else L=mid+;
- }
- lef=ans+;fa[q[ans]]=a[i].x;erase[++top]=q[ans];
- }
- for(rt i=top;i>=;i--)s.erase(erase[i]);top=;
- s.insert(a[i].x);
- }
- puts("ANSWER");
- for(rt i=;i<=n;i++)write(fa[i]),putchar(' '),writeln(i);flush;
- return ;
- }
Codeforces Round #542 (Div. 1) 题解的更多相关文章
- Codeforces Round #182 (Div. 1)题解【ABCD】
Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...
- Codeforces Round 542 (Div. 2)
layout: post title: Codeforces Round 542 (Div. 2) author: "luowentaoaa" catalog: true tags ...
- Codeforces Round #608 (Div. 2) 题解
目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...
- Codeforces Round #525 (Div. 2)题解
Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...
- Codeforces Round #528 (Div. 2)题解
Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...
- Codeforces Round #466 (Div. 2) 题解940A 940B 940C 940D 940E 940F
Codeforces Round #466 (Div. 2) 题解 A.Points on the line 题目大意: 给你一个数列,定义数列的权值为最大值减去最小值,问最少删除几个数,使得数列的权 ...
- Codeforces Round #677 (Div. 3) 题解
Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...
- Codeforces Round #665 (Div. 2) 题解
Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...
- Codeforces Round #160 (Div. 1) 题解【ABCD】
Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...
随机推荐
- PLSQL Developer图形化界面新建用户并授权并导入脚本
最近用了PLSQL Developer第三方的软件.记录一下实现新建用户并授权并导入脚本的功能. 第一步.切换sys用户(如果此处方法已经掌握,直接切换sys即可,就不用看这一步了) 首先检查当前登录 ...
- 解决在使用gensim.models.word2vec.LineSentence加载语料库时报错 UnicodeDecodeError: 'utf-8' codec can't decode byte......的问题
在window下使用gemsim.models.word2vec.LineSentence加载中文维基百科语料库(已分词)时报如下错误: UnicodeDecodeError: 'utf-8' cod ...
- springmvc上传文件错误The current request is not a multipart request
<1>在jsp页面的<head></head>标签里面加上<meta http-equiv="Content-Type" content= ...
- 关于ES6的module的循环加载
今天写js时,碰到了一个模块循环加载的错误,下面时例子: // testa.mjs import testb from './testb.mjs'; const {b} = testb; const ...
- scala的多种集合的使用(3)之遍历集合的方法
遍历集合的方法 1.用foreach循环遍历一个集合 foreach接收一个函数作为参数.定义的函数应该接收一个元素作为输入参数,然后不要返回任何的东西.输入的参数的类型应该匹配集合中的类型.随着fo ...
- 说说我心中的Linux系统
我不知道在阅读此篇文章的你,是一个什么样的人,或许你只是偶然看到此篇文章的路人,或许是对linux有兴趣但没接触过linux的圈外人,或许是已经入行没多久的菜鸟,或许是喜欢linux却学习不下去预备放 ...
- [代码]解析nodejs的require,吃豆人的故事
最近在项目中需要对nodejs的require关键字做解析,并且替换require里的路径.一开始我希望nodejs既然作为脚本语言,内核提供一个官方的parser库应该是一个稳定可靠又灵活的渠道,然 ...
- 滴滴 CTO 架构师 业务 技术 战役 时间 赛跑 超前 设计
滴滴打车CTO张博:生死战役,技术和时间赛跑-CSDN.NEThttps://www.csdn.net/article/2015-06-25/2825058-didi 滴滴出行首席架构师李令辉:业务的 ...
- 3 Eclipse 查看不了源码
Eclipse 查看源码时,报source not found问题,经查资料,需要配置环境变量才能查看到. 在用户变量或者系统变量下,配置CLASSPATH,值为JDK的lib路径:D:\Progra ...
- js 解决两值交换
总结七种办法来交换a和b的变量值 交换变量值方案一 最最最简单的办法就是使用一个临时变量了 不过使用临时变量的方法实在是太low了 var t; t = a; a = b; b = t; 首先把a ...