开学了住校了打不了深夜场

好难受啊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) 题解的更多相关文章

  1. Codeforces Round #182 (Div. 1)题解【ABCD】

    Codeforces Round #182 (Div. 1)题解 A题:Yaroslav and Sequence1 题意: 给你\(2*n+1\)个元素,你每次可以进行无数种操作,每次操作必须选择其 ...

  2. Codeforces Round 542 (Div. 2)

    layout: post title: Codeforces Round 542 (Div. 2) author: "luowentaoaa" catalog: true tags ...

  3. Codeforces Round #608 (Div. 2) 题解

    目录 Codeforces Round #608 (Div. 2) 题解 前言 A. Suits 题意 做法 程序 B. Blocks 题意 做法 程序 C. Shawarma Tent 题意 做法 ...

  4. Codeforces Round #525 (Div. 2)题解

    Codeforces Round #525 (Div. 2)题解 题解 CF1088A [Ehab and another construction problem] 依据题意枚举即可 # inclu ...

  5. Codeforces Round #528 (Div. 2)题解

    Codeforces Round #528 (Div. 2)题解 A. Right-Left Cipher 很明显这道题按题意逆序解码即可 Code: # include <bits/stdc+ ...

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

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

  7. Codeforces Round #677 (Div. 3) 题解

    Codeforces Round #677 (Div. 3) 题解 A. Boring Apartments 题目 题解 简单签到题,直接数,小于这个数的\(+10\). 代码 #include &l ...

  8. Codeforces Round #665 (Div. 2) 题解

    Codeforces Round #665 (Div. 2) 题解 写得有点晚了,估计都官方题解看完切掉了,没人看我的了qaq. 目录 Codeforces Round #665 (Div. 2) 题 ...

  9. Codeforces Round #160 (Div. 1) 题解【ABCD】

    Codeforces Round #160 (Div. 1) A - Maxim and Discounts 题意 给你n个折扣,m个物品,每个折扣都可以使用无限次,每次你使用第i个折扣的时候,你必须 ...

随机推荐

  1. selenium跳过webdriver检测并模拟登录淘宝

    目录 简介 编写思路 使用教程 演示图片 源代码 @(文章目录) 简介 模拟登录淘宝已经不是一件新鲜的事情了,过去我曾经使用get/post方式进行爬虫,同时也加入IP代理池进行跳过检验,但随着大型网 ...

  2. url 的正则表达式:path-to-regexp

    概述 该工具库用来处理 url 中地址与参数,能够很方便得到我们想要的数据. js 中有 RegExp 方法做正则表达式校验,而 path-to-regexp 可以看成是 url 字符串的正则表达式. ...

  3. 转:互斥锁解决同时上传数据丢失BUG

    互斥锁:在一个线程修改变量时加锁,则其他变量阻塞,等待加锁的变量解锁后再执行,避免数据覆盖或者其他的异常情况. 原子操作: 所谓原子操作是指不会被线程调度机制打断的操作:这种操作一旦开始,就一直运行到 ...

  4. Python----支持向量机SVM

    1.1. SVM介绍 SVM(Support Vector Machines)——支持向量机.其含义是通过支持向量运算的分类器.其中“机”的意思是机器,可以理解为分类器. 1.2. 工作原理 在最大化 ...

  5. Spark报错

    1. Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at com.mysql.jdb ...

  6. [转帖]Zoom

    Zoom美国上市:华裔创始人为大股东 创业想法来自“异地恋” https://baijiahao.baidu.com/s?id=1631166070308020680&wfr=spider&a ...

  7. 关于TVWALL 通过AS300获取状态连接失败

    昨天晚会突然之间频繁出现tvwall视频软件,断开AS300管理软件的故障 发现AS300当中的cms服务进程,占用内存250M左右,一般情况下估计就是50M左右,增长了不少 无奈之下,只有重启AS3 ...

  8. win10 安装docker

    看介绍说docker不支持win10家庭版,但是一搜安装教程也有好多在家庭版上安装的,而且也不麻烦,不知道咋回事 1.查看虚拟化状态 一开始我的是没有开启的,从bios开启的 一般是开始按F2,进入b ...

  9. Vue js 的生命周期(看了就懂)

    转自: https://blog.csdn.net/qq_24073885/article/details/60143856 用Vue框架,熟悉它的生命周期可以让开发更好的进行. 首先先看看官网的图, ...

  10. 【dp】友好城市

    题目一: [题目描述] Palmia国有一条横贯东西的大河,河有笔直的南北两岸,岸上各有位置各不相同的N个城市.北岸的每个城市有且仅有一个友好城市在南岸,而且不同城市的友好城市不相同. 每对友好城市都 ...