2024.8.8模拟赛16
1.2024.7.18模拟赛12.2024.7.19模拟赛23.2024.7.20模拟赛34.2024.7.21模拟赛45.2024.7.22模拟赛56.2024.7.23 模拟赛67.2024.7.25模拟赛78.2024.7.26模拟赛89.2024.7.27模拟赛910.2024.7.28 模拟赛1011.2024.7.29模拟赛1112.2024.7.31模拟赛1213.2024.8.1 模拟赛1314.2024.8.6 模拟赛 1415.2024.8.7 模拟赛 15
16.2024.8.8模拟赛16
17.2024.8.10模拟赛1718.2024.8.18 模拟赛 2219.2024.8.19 模拟赛 2420.小集训21.2024.9.23 模拟赛 CSP 322.2024.9.24 模拟赛 CSP423.2024.9.25 模拟赛 多校24.2024.9.27 模拟赛 CSP525.2024.9.28 模拟赛 CSP626.2024.9.30 模拟赛 CSP727.2024.10.7 模拟赛 多校328.2024.?.?? 模拟赛 ???模拟赛
重拾题解(刚刚写过一版忘保存了)
T1
其实就是个最长公共子序列的变形。把一样的数才匹配换成有倍数关系就匹配。
最长公共子序列:一般转化为最长上升子序列,即在一个串中的数
本题需要找到在第一个串中每个数的倍数在第二个串中的位置,由于调和级数,只会有
code
#include<bits/stdc++.h>
using namespace std;
const int N = 2e5+5;
int n,a[N],b[N],pos[N],f[N],c[N],ans;
vector<int> v[N];
inline bool cmp(int &x,int &y) {return x>y;}
inline void add(int x,int v)
{
for(;x<=n;x+=(x&-x)) c[x]=max(c[x],v);
}
inline int que(int x)
{
int res=0;
for(;x;x-=(x&-x)) res=max(c[x],res);
return res;
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) scanf("%d",&b[i]),pos[b[i]]=i;
for(int i=1;i<=n;i++)
{
for(int j=1;j*a[i]<=n;j++)
v[i].push_back(pos[j*a[i]]);
sort(v[i].begin(),v[i].end(),cmp);
for(int j:v[i])
{
f[j]=max(f[j],que(j-1)+1);
ans=max(ans,f[j]);
add(j,f[j]);
}
}
printf("%d\n",ans);
return 0;
}
T2 大爷的字符串题
转化题意,就是查询区间众数。
然后开始莫队
一种直接用回滚,另一种可以维护每一个数在区间中的出现次数,然后再维护出现次数的出现次数。
注意离散化。
其实挺板的。
code
#include<cstdio>
#include<math.h>
#include<algorithm>
#include<unordered_map>
using namespace std;
#define mx(x,y) (x>y?x:y)
#define LL long long
const int N = 2e5+5;
int n,m,a[N],bl[N],tot;
struct Q {int l,r,id;} q[N];
int cnt[N],Cnt[N],ans[N],now;
unordered_map<int,int> mp;
inline bool cmp(Q &x,Q &y)
{
return bl[x.l]==bl[y.l]?((bl[x.l]&1)?(x.r<y.r):(x.r>y.r)):bl[x.l]<bl[y.l];
}
inline void add(int x)
{
Cnt[cnt[x]]--;
cnt[x]++;
Cnt[cnt[x]]++;
now=mx(now,cnt[x]);
}
inline void del(int x)
{
Cnt[cnt[x]]--;
if(now==cnt[x]&&Cnt[cnt[x]]==0) now--;
cnt[x]--;
Cnt[cnt[x]]++;
}
void mq()
{
for(int i=1,l=1,r=0;i<=m;i++)
{
int tl=q[i].l,tr=q[i].r;
while(l<tl) del(a[l++]);
while(l>tl) add(a[--l]);
while(r>tr) del(a[r--]);
while(r<tr) add(a[++r]);
ans[q[i].id]=-now;
}
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d%d",&n,&m); int len=n/sqrt(m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]),bl[i]=(i-1)/len+1;
if(!mp[a[i]]) mp[a[i]]=++tot;
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;
sort(q+1,q+1+m,cmp);
mq();
for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
return 0;
}
T3 Arpa’s letter-marked tree and Mehrdad’s Dokhtar-kosh paths
启发式合并。
注意理解题意,是每棵子树内最长的合法链。
因为只有
至于串的长度可以直接用深度差分得到。
依旧运用差分的思想,我们预处理根到每个点路径异或和,然后就可以从中截取一段路径。(以下状态都表示到根的异或和)
其实我们最终就是要找到某两个点之间的路径异或和为
现在我们有了判断合法的方法,考虑如何对每一棵子树进行求解。如果直接遍历一定是
我们选择整体维护重链的信息(全维护开不下),然后暴力遍历轻链,由于每次合并都会使需要遍历的轻链大小至少翻倍,所以复杂度
然后每次遍历一棵轻链,在已经合并的子树里找有没有能匹配合法的。然后注意我们维护的只是重儿子所在子树,所以对于那些轻儿子的信息要在处理完清空。
code
#include<bits/stdc++.h>
using namespace std;
#define mx(x,y) (x>y?x:y)
const int N = 1e6+5;
int n,ans[N];
int head[N],tot;
struct E {int u,v,w;} e[N<<1];
inline void add(int u,int v,int w) {e[++tot]={head[u],v,w}; head[u]=tot;}
int sz[N],son[N],dep[N],dfn[N],cnt,L[N],R[N],book[N*10],d[N];
inline void dfs(int u,int f)
{
sz[u]=1; dep[u]=dep[f]+1; L[u]=++cnt; dfn[cnt]=u;
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v; d[v]=d[u]^e[i].w;
dfs(v,u); sz[u]+=sz[v];
if(sz[son[u]]<sz[v]) son[u]=v;
}
R[u]=cnt;
}
inline void dfs2(int u,bool keep)
{
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v; if(v==son[u]) continue;
dfs2(v,0); ans[u]=mx(ans[u],ans[v]);
}
if(son[u]) dfs2(son[u],1),ans[u]=mx(ans[u],ans[son[u]]);
if(book[d[u]]) ans[u]=mx(ans[u],book[d[u]]-dep[u]);
for(int i=0;i<22;i++) if(book[d[u]^(1<<i)]) ans[u]=mx(ans[u],book[d[u]^(1<<i)]-dep[u]);
book[d[u]]=mx(book[d[u]],dep[u]);
for(int i=head[u];i;i=e[i].u)
{
int v=e[i].v; if(v==son[u]) continue;
for(int j=L[v];j<=R[v];j++)
{
int x=dfn[j];
if(book[d[x]]) ans[u]=mx(ans[u],book[d[x]]+dep[x]-(dep[u]<<1));
for(int k=0;k<22;k++) if(book[d[x]^(1<<k)]) ans[u]=mx(ans[u],book[d[x]^(1<<k)]+dep[x]-(dep[u]<<1));
}
for(int j=L[v];j<=R[v];j++)
{
int x=dfn[j];
book[d[x]]=mx(book[d[x]],dep[x]);
}
}
if(!keep) for(int i=L[u];i<=R[u];i++) book[d[dfn[i]]]=0;
}
int main()
{
// freopen("in.in","r",stdin);
// freopen("out.out","w",stdout);
scanf("%d",&n);
for(int i=2;i<=n;i++)
{
int x; char c; scanf("%d %c",&x,&c);
add(x,i,1<<(c-'a'));
}
dfs(1,1); dfs2(1,1);
for(int i=1;i<=n;i++) printf("%d ",ans[i]);
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 因为Apifox不支持离线,我果断选择了Apipost!
· 通过 API 将Deepseek响应流式内容输出到前端