隐藏页面特效

Codeforces Round #809 (Div. 2)

1|0Preface


由于受YKH之约7/31号晚上要打CF,所以赶紧打点CF复健

这场比赛只有Div2,很适合现在的我找找自信(被虐)


2|0A. Another String Minimization Problem


不难发现每对位置之间相互独立,因此对于每一对贪心地先放前面的A,有了再扔后面即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=55; int t,n,m,x,vis[N]; int main() { for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d%d",&n,&m),i=1;i<=m;++i) vis[i]=0; for (i=1;i<=n;++i) { scanf("%d",&x); int mi=min(x,m+1-x),mx=max(x,m+1-x); if (!vis[mi]) vis[mi]=1; else vis[mx]=1; } for (i=1;i<=m;++i) putchar(vis[i]?'A':'B'); putchar('\n'); } return 0; }

3|0B. Making Towers


把每种颜色的位置单独拿出来看,不难发现只要对于两个位置x,y(x<y),只要yx是奇数就可以把这两个位置连起来

fi表示以i为结尾时的答案,不难发现转移的时候我们只关心fj(j<i且j和i的奇偶性不同)的最大值

因此直接用两个数记录一下下标是奇数和偶数时的情况即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=100005; int t,n,x,f[N][2]; int main() { for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),i=1;i<=n;++i) f[i][0]=f[i][1]=0; for (i=1;i<=n;++i) scanf("%d",&x),f[x][i&1]=f[x][(i&1)^1]+1; for (i=1;i<=n;++i) printf("%d%c",max(f[i][0],f[i][1]),i==n?'\n':' '); } return 0; }

4|0C. Qpwoeirut And The City


首先考虑满足题意的房子数量最大,一眼奇偶分类

n为奇数时,显然所有的偶数下标的房子都得是cool的,直接算即可

n为偶数时,我们把中间的数相邻两个看成一组,假设在这一组中选前一个变cool是操作1,选后一个变cool是操作2

那么显然一种合法方案一定是一段连续的1再接上一段连续的2

直接前缀后缀贡献统计后枚举即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=100005; int t,n,h[N]; long long pre[N],suf[N],ans; inline int fix(CI x) { return max(max(h[x-1],h[x+1])-h[x]+1,0); } int main() { for (scanf("%d",&t);t;--t) { RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&h[i]); if (ans=0,n&1) { for (i=2;i<n;i+=2) ans+=fix(i); } else { for (i=2;i<n;i+=2) pre[i>>1]=pre[i-2>>1]+fix(i); for (suf[n>>1]=0,i=n-1;i>1;i-=2) suf[i>>1]=suf[i+2>>1]+fix(i); for (ans=1e18,i=0;i<(n>>1);++i) ans=min(ans,pre[i]+suf[i+1]); } printf("%lld\n",ans); } return 0; }

5|0D1. Chopping Carrots (Easy Version)


数据范围明显O(n2),直接考虑暴力

一个显然的想法,我们暴枚min1in(aipi)的值x,考虑对于每个数ai,在满足aipix的条件下pi的最大值,此时显然aipi的值最小

对于aipix,显然可转化为aixpi,即此时pimin(aix,k),对所有ai的情形取个最大值即可

#include<cstdio> #include<iostream> #define RI register int #define CI const int& using namespace std; const int N=3005; int t,n,m,ans,a[N]; int main() { for (scanf("%d",&t);t;--t) { RI i,j; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&a[i]); for (ans=a[n],i=0;i<=a[1];++i) { int pos=0; for (j=1;j<=n;++j) pos=max(pos,a[j]/min(i?a[j]/i:m,m)); ans=min(ans,pos-i); } printf("%d\n",ans); } return 0; }

6|0D2. Chopping Carrots (Hard Version)


水平退化到一个除法分块调了半天真是醉了……

考虑在D1的基础上优化,我们先来找下性质

首先不难发现对于每一个ai,它整除后得到的数是ai级别的,我们假设这些数为s1,s2,,sk(s1<s2<<sk)

由于每个ai相互独立,因此我们可以把问题转化为:

一个数轴上有若干点,点的坐标就是sj,同时每个点都有一个颜色i

现在要找一个最小的区间满足在这个区间内包含了所有颜色的点

不难想到用fi表示i为左端点时合法区间右端点的最小值,然后每次枚举一个ai求出它的s数组更新f数组即可

考虑对于一对相邻的sj,sj+1,显然有转移fi=max(fi,sj+1),i(sj,sj+1]

然后我们发现一个显然的性质,fi非降的,因此我们可以把修改打一个标记在sj+1处,最后用前缀max统计下即可

时间复杂度O(nan)

#include<cstdio> #include<vector> #include<algorithm> #include<iostream> #define RI register int #define CI const int& using namespace std; typedef vector <int>::iterator VI; const int N=100005; int t,n,m,ans,a[N],pos[N]; vector <int> s; VI L,R; int main() { for (scanf("%d",&t);t;--t) { RI i,l,r; for (scanf("%d%d",&n,&m),i=1;i<=n;++i) scanf("%d",&a[i]); for (i=0;i<=a[n];++i) pos[i]=i; for (i=1;i<=n;++i) { s.clear(); for (l=1;l<=min(m,a[i]);l=r+1) { int ret=a[i]/l; s.push_back(ret); r=ret?a[i]/ret:a[i]; } s.push_back(0); reverse(s.begin(),s.end()); s.push_back(1e9); for (L=R=s.begin(),++R;R!=s.end();++L,++R) pos[*L+1]=max(pos[*L+1],*R); } for (ans=1e9,i=1;i<=a[n];++i) pos[i]=max(pos[i],pos[i-1]),ans=min(ans,pos[i]-i); printf("%d\n",ans); } return 0; }

7|0E. Qpwoeirut and Vertices


这是Div2的题吗?有点难度的说可能是因为现在打个LCA都费劲吧

首先我们要知道一个叫Kruskal重构树的东西(话说我之前学OI的时候都不会),它在处理图上带阈值联通问题的一大利器

当我们建出重构树后,对每个虚拟节点赋以边的标号为权值

不难发现两点x,y的最小联通代价就是它们LCA的权值

E.g. 对于样例

Pic1

我们可以建出它的Kruskal重构树(方点代表虚拟节点)

例如对于2,3两点,它们的LCA是7点,权值为2,因此至少需要前两条边才能联通

接下来考虑询问,不难发现它的要求是这个区间内的所有点都在一个连通块内

我们不妨假设fi=ValLCA(i,i+1),那么根据联通的转递性对于一个询问l,r,最后的答案就是maxli<rfi

直接预处理出fi之后用RMQ处理询问即可,注意特判l=r的情形

复杂度O(nlogn)

#include<cstdio> #include<iostream> #include<algorithm> #define RI register int #define CI const int& using namespace std; const int N=200005; struct edge { int x,y; }e[N]; int t,n,m,q,l,r,tot,val[N]; namespace DSU { int fa[N]; inline void clear(void) { for (RI i=1;i<=n;++i) fa[i]=i; } inline int getfa(CI x) { return fa[x]==x?x:fa[x]=getfa(fa[x]); } inline bool query(CI x,CI y) { return getfa(x)==getfa(y); } }; namespace T { struct edge { int to,nxt; }e[N<<1]; int cnt,head[N],dep[N],anc[N][20]; inline void addedge(CI x,CI y) { e[++cnt]=(edge){y,head[x]}; head[x]=cnt; e[++cnt]=(edge){x,head[y]}; head[y]=cnt; }; inline void clear(void) { RI i,j; for (i=1;i<=tot;++i) for (j=0;j<19;++j) if (anc[i][j]) anc[i][j]=0; else break; for (i=1;i<=tot;++i) head[i]=val[i]=0; cnt=0; tot=n; } inline void link(int x,int y,CI id) { val[++tot]=id; DSU::fa[tot]=tot; x=DSU::getfa(x); y=DSU::getfa(y); addedge(x,tot); addedge(y,tot); DSU::fa[x]=DSU::fa[y]=tot; } #define to e[i].to inline void DFS(CI now=tot,CI fa=0) { dep[now]=dep[anc[now][0]=fa]+1; RI i; for (i=0;i<19;++i) if (anc[now][i]) anc[now][i+1]=anc[anc[now][i]][i]; else break; for (i=head[now];i;i=e[i].nxt) if (to!=fa) DFS(to,now); } inline void DEBUG(CI now=tot,CI fa=0) { printf("%d : ",now); RI i; for (i=head[now];i;i=e[i].nxt) if (to!=fa) printf("%d ",to); putchar('\n'); for (i=head[now];i;i=e[i].nxt) if (to!=fa) DEBUG(to,now); } #undef to inline int getlca(int x,int y) { if (dep[x]<dep[y]) swap(x,y); RI i; for (i=19;~i;--i) if (dep[anc[x][i]]>=dep[y]) x=anc[x][i]; if (x==y) return x; for (i=19;~i;--i) if (anc[x][i]!=anc[y][i]) x=anc[x][i],y=anc[y][i]; return anc[x][0]; } }; namespace RMQ { int log[N],mx[N][20]; inline void init(void) { RI i,j; for (i=2;i<n;++i) log[i]=log[i>>1]+1; for (i=1;i<n;++i) mx[i][0]=val[T::getlca(i,i+1)]; for (j=1;(1<<j)<n;++j) for (i=1;i+(1<<j)-1<n;++i) mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]); } inline int query(CI l,CI r) { int k=log[r-l+1]; return max(mx[l][k],mx[r-(1<<k)+1][k]); } }; int main() { //freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout); for (scanf("%d",&t);t;--t) { RI i; scanf("%d%d%d",&n,&m,&q); DSU::clear(); T::clear(); for (i=1;i<=m;++i) scanf("%d%d",&e[i].x,&e[i].y); for (i=1;i<=m;++i) if (!DSU::query(e[i].x,e[i].y)) T::link(e[i].x,e[i].y,i); for (T::DFS(),RMQ::init(),i=1;i<=q;++i) scanf("%d%d",&l,&r),printf("%d%c",l==r?0:RMQ::query(l,r-1),i==q?'\n':' '); } return 0; }

8|0Postscript


现在水平确实不行,D2和E都做不来,太菜太菜


__EOF__

本文作者hl666
本文链接https://www.cnblogs.com/cjjsb/p/16532983.html
关于博主:复活的ACM新生,目前爱好仅剩Gal/HBR/雀魂/单机/OSU
版权声明:转载请注明出处
声援博主:欢迎加QQ:2649020702来DD我
posted @   空気力学の詩  阅读(89)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!
历史上的今天:
2020-07-29 Luogu P6620 [省选联考 2020 A 卷] 组合数问题
2020-07-29 Luogu P6631 [ZJOI2020] 序列
2020-07-29 Luogu P6630 [ZJOI2020] 传统艺能
2020-07-29 Luogu P6633 [ZJOI2020] 抽卡
2018-07-29 数列分块入门九题(二):LOJ6280~6282
2018-07-29 数列分块入门九题(一):LOJ6277~6279
点击右上角即可分享
微信分享提示