暑假集训CSP提高模拟 16
\]
如果你实在不会算 \(\forall f_{x}=f_{x-1}+f_{x-2}\) 的情况,那你可以把它特化成斐波那契数列. 如果你连斐波那契数列特化的上式都算不出来,那么你应该看 这一篇 的第 7.7 章
A.九次九日九重色
今天先去研究了一下 \(n\log n\) 的最长上升子序列和最长公共子序列怎么写:
根据贪心思路,我们可以将最长上升子序列问题的求解优化至 \(n\log n\)
考虑到对于每次转移,我们都可以记录下当前序列最末尾的数字,可以想到的是,当前序列末尾数字越小,则可能被填入子序列的数字就越多,因此末尾更小的序列可能就是决策更优的,因此我们每次都保留这样的序列向后拓展.
也就是,我们使用数组 \(f_{i}\) 表示当枚举到第 \(i\) 位时,全部最长上升子序列中,最小的末尾元素值,则可以发现:
- 当新的元素值更大的时候,符合上升条件,直接填到末尾
- 当新的元素值更小的时候,虽然不符合上升条件,但是符合更新条件,可能会导致更优的决策,因此我们向前找到第一个能放当前值的 \(i\) 进行更新.
代码如下:
#include<bits/stdc++.h>
using namespace std;
int n;
int a[100001];
int f[100001];
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;++i){
cin>>a[i];
}
memset(f,0x3f,sizeof f);
f[1]=a[1];
int len=1;
for(int i=2;i<=n;++i){
int l=0,r=len;
if(a[i]>f[len]){
f[++len]=a[i];
}
else{
f[lower_bound(f+1,f+len+1,a[i])-f]=a[i];
}
}
cout<<len<<endl;
}
字序列是一个字符串中有序的一段,即序列中的每个数在原序列内都从左到右排列,公共子序列即为几个字符串都含有的子序列.
\]
类似最长公共子串,但不一样的是,假如 \(x[i] \neq y[j]\),不要急着清零,因为最长公共子序列并不需要严格相邻. 此时应该跳过不相等的内容,那么如何跳过呢? 我们采用了继承相邻状态的方法.
假如序列中的每个数都仅仅出现过一次,那么我们可以考虑对上述 \(n^{2}\) 算法进行优化.
A:3 2 1 4 5
B:1 2 3 4 5
我们不妨给它们重新标个号:把 \(3\) 标成 \(a\),把 \(2\) 标成 \(b\),把 \(1\) 标成 \(c\),以此类推,目的是将 \(A\) 变为一个递增的序列,于是变成:
A: a b c d e
B: c b a d e
这样标号之后,最长公共子序列长度显然不会改变. 但是出现了一个性质:
两个序列的子序列,一定是 \(A\) 的子序列. 而A本身就是单调递增的,因此这个子序列是单调递增的
换句话说,只要这个子序列在 \(B\) 中单调递增,它就是 \(A\) 的子序列
哪个最长呢?当然是 \(B\) 的最长上升子序列最长
因此,我们只需要在 \(n\log n\) 的时间复杂度内求出 \(B\) 的最长上升子序列即可
因此这个题也可以转化成最长公共子序列问题,只不过在这里我们的 “公共” 是整除
#include<bits/stdc++.h>
using namespace std;
int n;
int p[200001],q[200001];
int a[200001];
int f[200001];
struct pai{
int a,b;
bool operator <(const pai &A)const{
if(a==A.a) return b>A.b;
return a<A.a;
}
};
vector<pai>v;
map<int,int>mp;
int posp[200001],posq[200001];
int c[200001];
int lowbit(int x){return x&-x;}
int ask(int x){
int ans=0;
if(x<=0) return 0;
while(x){
ans=max(ans,c[x]);
x-=lowbit(x);
}
return ans;
}
void update(int x,int val){
if(x<=0) return;
while(x<=n){
c[x]=max(c[x],val);
x+=lowbit(x);
}
}
vector<int>pos[200001];
int main(){
ios::sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;++i){
cin>>p[i];
posp[p[i]]=i;
}
for(int i=1;i<=n;++i){
cin>>q[i];
posq[q[i]]=i;
}
for(int i=1;i<=n;++i){
for(int j=i;j<=n;j+=i){
if(posq[j]) pos[i].push_back(posq[j]);
}
// for(int i:pos[i]) cout<<i<<" ";cout<<endl;
sort(pos[i].begin(),pos[i].end());
reverse(pos[i].begin(),pos[i].end());
}
int ans=0;
for(int i=1;i<=n;i++){
for(auto v:pos[p[i]]){
int j=v;
f[j]=ask(j);
f[j]=max(ask(j-1)+1,f[j]);
ans=max(ans,f[j]);
update(j,f[j]);
}
}
cout<<ans<<endl;
// sort(v.begin(),v.end());
// for(int i=0;i<=v.size()-1;++i){
// cout<<v[i].a<<" "<<v[i].b<<endl;
// a[i+1]=v[i].b;
// }
// memset(f,0x7f,sizeof f);
// f[1]=a[1];
// int len=1;
// for(int i=2;i<=n;++i){
// int l=0,r=len;
// if(a[i]>f[len]){
// f[++len]=a[i];
// }
// else{
// f[lower_bound(f+1,f+len+1,a[i])-f]=a[i];
// }
// }
// cout<<len<<endl;
}
B.天色天歌天籁音
写的普通莫队,赛时我在大黄旁边看他写分块,数组开了快一个 G,给我急死了
这是用莫队求区间众数的基本套路:先开一个桶,再开一个桶的桶,用来记录什么时候该转移了. 可以注意到莫队每次进行转移都只会至多使一个桶的值变化 \(1\),因此若当前数量的桶的数量为零,则说明需要给众数减一,否则,若新加入的桶的数量是更大的,则更新最优答案.
还是说一下这个题为什么是区间众数吧,注意到我们每找出一个上升子序列,都会贡献 \(1\) 的答案. 因此实际上这个题的目标是让我们将原数列分成若干单调递增的子序列,最小化切分总数量. 因此可以考虑每次都贪心地从小到大能拿就拿. 最后剩下的一定是出现次数最多的,即只有众数会对答案有影响.
#include<bits/stdc++.h>
using namespace std;
int n,m;
int len,locate[250001];
struct ques{
int id,l,r;
bool operator <(const ques &A)const{
if(locate[l]!=locate[A.l]) return locate[l]<locate[A.l];
if(locate[l]&1) return r<A.r;
return r>A.r;
}
}q[250001];
int a[250001],cnt[250001],totcnt[250001],ans;
map<int,int>mp;int mpcnt=0;
int nowl,nowr;
int anss[250001];
inline void prew(){
len=sqrt(m);
if(!m) len=sqrt(n);
for(int i=1;i<=n;++i){
locate[i]=i/len+(i%len!=0);
}
}
inline void reduce(int pos){
totcnt[cnt[a[pos]]]--;
if(totcnt[cnt[a[pos]]]==0 and ans==cnt[a[pos]]) ans--;
cnt[a[pos]]--;
// cout<<"reduce "<<pos<<": "<<ans<<endl;
}
inline void add(int pos){
cnt[a[pos]]++;
if(totcnt[cnt[a[pos]]]==0 and ans<cnt[a[pos]]) ans=cnt[a[pos]];
totcnt[cnt[a[pos]]]++;
// cout<<"add "<<pos<<": "<<ans<<endl;
}
int main(){
// freopen("大样例/T2.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d %d",&n,&m);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
if(!mp.count(a[i])){
mp[a[i]]=++mpcnt;
a[i]=mpcnt;
}
else a[i]=mp[a[i]];
}
for(int i=1;i<=m;++i){
scanf("%d %d",&q[i].l,&q[i].r);
q[i].id=i;
}
prew();
sort(q+1,q+m+1);
nowl=q[1].l;nowr=q[1].l;
ans=1;cnt[a[q[1].l]]++;totcnt[cnt[a[q[1].l]]]++;
for(int i=1;i<=m;++i){
while(nowl<q[i].l) reduce(nowl++);
while(nowl>q[i].l) add(--nowl);
while(nowr<q[i].r) add(++nowr);
while(nowr>q[i].r) reduce(nowr--);
anss[q[i].id]=ans;
}
for(int i=1;i<=m;++i){
printf("%d\n",-anss[i]);
}
}
暑假集训CSP提高模拟 16的更多相关文章
- 2015UESTC 暑假集训总结
day1: 考微观经济学去了…… day2: 一开始就看了看一道题目最短的B题,拍了半小时交了上去wa了 感觉自己一定是自己想错了,于是去拍大家都过的A题,十分钟拍完交上去就A了 然后B题写了一发暴力 ...
- STL 入门 (17 暑假集训第一周)
快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...
- 20190820 Tue 集训总结&NOIP模拟 27
低谷度过了? 但是skyh阿卡了,还是反衬出我的辣鸡. T1知道要sort,却忘了判重,正解不如暴力分高,555. T2成功化出正解柿子,然后化过头了,化出了无法DP的柿子. 果然不够强,大神们一眼就 ...
- 牛客网NOIP赛前集训营-提高组(第四场)游记
牛客网NOIP赛前集训营-提高组(第四场)游记 动态点分治 题目大意: \(T(t\le10000)\)组询问,求\([l,r]\)中\(k(l,r,k<2^{63})\)的非负整数次幂的数的个 ...
- 牛客网NOIP赛前集训营-提高组(第四场)B区间
牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1 \dots a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...
- 牛客网NOIP赛前集训营-提高组(第四场)B题 区间
牛客网NOIP赛前集训营-提高组(第四场) 题目描述 给出一个序列 a1, ..., an. 定义一个区间 [l,r] 是好的,当且仅当这个区间中存在一个 i,使得 ai 恰好等于 al, al+1, ...
- 牛客网NOIP赛前集训营-普及组(第二场)和 牛客网NOIP赛前集训营-提高组(第二场)解题报告
目录 牛客网NOIP赛前集训营-普及组(第二场) A 你好诶加币 B 最后一次 C 选择颜色 D 合法括号序列 牛客网NOIP赛前集训营-提高组(第二场) A 方差 B 分糖果 C 集合划分 牛客网N ...
- 【java提高】(16)---java注解(Annotation)
java提高(16)---java注解 注解含义注解是JDK1.5之后才有的新特性,它相当于一种标记,在程序中加入注解就等于为程序打上某种标记,之后又通过类的反射机制来解析注解. 一.JDK自带注解 ...
- 暑假集训Day2 互不侵犯(状压dp)
这又是个状压dp (大型自闭现场) 题目大意: 在N*N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. ...
- 暑假集训Day1 整数划分
题目大意: 如何把一个正整数N(N长度<20)划分为M(M>=1)个部分,使这M个部分的乘积最大.N.M从键盘输入,输出最大值及一种划分方式. 输入格式: 第一行一个正整数T(T<= ...
随机推荐
- ngnix简介和基础
一.Nginx简介 Nginx 是一个高性能的HTTP和反向代理服务器,同时也是一个IMAP/POP3/SMTP代理服务器 是一个模块化软件 [1].安装nginx 使用源码包编译安装 cd /opt ...
- 微软CrowdStrike驱动蓝屏以及内核签名
原因 当Windows操作系统遇到严重错误导致系统崩溃时,屏幕显示为蓝色,通常伴有错误代码和信息,这被称为"蓝屏死机"(Blue Screen of Death,简称BSOD) h ...
- selenium获取验证码截图
获取验证码截图代码: 获取验证码代码: #!/user/bin/env python3 # -*- coding: utf-8 -*- import requests from selenium im ...
- pytest + allure2.x 踩坑-报告无数据
我按照网上的教程,在用pytest生成完allure可以使用的json数据之后,然后再用allure生成报告,打开,发现我生成的报告中没有数据显示. 1.首先我用pytest生成数据是没有问题的 2. ...
- stable diffusion 入门教程
sd基础 工作原理&入门 输入提示词后 有文本编码器将提示词编译成特征向量,vae编码器将特征向量传入潜空间内,特征向量在潜空间内不断降噪,最后通过vae解码器将降噪之后的特征向量 解码成一个 ...
- python中基于tcp协议与udp的通信
python中基于tcp协议与udp的通信(数据传输) 一.TCP协议介绍 流式协议(以数据流的形式通信传输) 安全协议(收发信息都需收到确认信息才能完成收发,是一种双向通道的通信) tcp协议在 ...
- ComfyUI插件:ComfyUI Impact 节点(四)
前言: 学习ComfyUI是一场持久战,而 ComfyUI Impact 是一个庞大的模块节点库,内置许多非常实用且强大的功能节点 ,例如检测器.细节强化器.预览桥.通配符.Hook.图片发送器.图片 ...
- URDF使用语法【万字解析赶紧码住】 —— 机器人统一描述文件格式(Unified Robot Description Format)
原文地址: https://zhuanlan.zhihu.com/p/665269288 具体内容略,请参照原文.
- 树莓派3b+ 系统(Raspbian)环境搭建以及配置
多年前购入树莓派3b+板子一块,一直没时间弄,近期疫情假期在家翻出来打算鼓捣鼓捣. 1. 树莓派系统下载: 链接地址: https://www.raspberrypi.org/downloads ...
- 机器学习中的权重衰退 —— 深度学习中的权重衰退 —— 权重衰退 —— weight decay
在看代码时看到了这个概念,以前虽然也看到过但是没有太在意,再次看到于是研究了一下. 引自: https://sota.jiqizhixin.com/models/methods/0bdb8f87-9c ...