Preface

闲来无事打打CF,就近找了场Div1打打

这场感觉偏简单,比赛时艹穿的人都不少,也没有3000+的题

两三个小时就搞完了吧(F用随机水过去了)


A. MP3

题意不好理解,没用翻译看了好久然后就看错了,后来发现是个SB题

考虑我们将数字排序+离散化之后就可以知道一个区间外有多少个数,可以直接计算答案

然后发现这个区间的移动有单调性,因此直接two points扫一下就好了

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=400005;
int n,lim,num,log_[N],a[N],rst[N],L[N],R[N],ans=1e9;
int main()
{
RI i,pos; for (scanf("%d%d",&n,&lim),lim*=8,i=1;i<=n;++i)
scanf("%d",&a[i]),rst[i]=a[i],log_[i]=ceil(log2(i));
sort(a+1,a+n+1); sort(rst+1,rst+n+1); num=unique(rst+1,rst+n+1)-rst-1;
for (i=1;i<=n;++i) R[a[i]=lower_bound(rst+1,rst+num+1,a[i])-rst]=i;
for (i=n;i;--i) L[a[i]]=i; for (i=pos=1;i<=num;++i)
{
while (pos<=i&&1LL*log_[i-pos+1]*n>lim) ++pos;
ans=min(ans,L[pos]-1+n-R[i]);
}
return printf("%d",ans),0;
}

B. Welfare State

题目大意就是单点修改和全局取\(\max\)(将所有数与一个数取\(\max\)),输出最后的序列

理解题意就很简单,我们记录下一个点最后一次被单点修改的值与时间,然后在所有全局取\(\max\)的操作中找一个时间在它后面的最大值尝试更新这个值即可

后缀\(\max\)+二分即可完成

#include<cstdio>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=200005;
int n,x,q,opt,y,tim[N],lst[N],et[N],val[N],mx[N],tot;
int main()
{
//freopen("B.in","r",stdin); freopen("B.out","w",stdout);
RI i; for (scanf("%d",&n),i=1;i<=n;++i) scanf("%d",&lst[i]);
for (scanf("%d",&q),i=1;i<=q;++i)
{
scanf("%d%d",&opt,&x); if (opt^1) et[++tot]=i,val[tot]=x;
else scanf("%d",&y),tim[x]=i,lst[x]=y;
}
for (i=tot;i;--i) mx[i]=max(mx[i+1],val[i]); for (i=1;i<=n;++i)
printf("%d ",max(lst[i],mx[lower_bound(et+1,et+tot+1,tim[i])-et]));
return 0;
}

C. Matching vs Independent Set

思博题,我都想了些什么鬼东西啊

考虑那\(3n\)个点一定有着什么限制,那么我们考虑以下算法:

  1. 扫一遍所有边,若这条边的两个端点都没有被匹配过就匹配这条边,记此时匹配过的边数为\(cnt\)
  2. 若\(cnt\ge n\)则得出了一个合法匹配
  3. 否则在剩下的点中任取\(n\)个就是独立集

考虑这个算法的正确性,显然当\(cnt\ge n\)时能得出合法匹配,故若\(cnt<n\),则剩下的两两无边相连的点数就是\(3n-2\cdot cnt>n\),因此一定能得到答案

#include<cstdio>
#define RI register int
#define CI const int&
using namespace std;
const int N=3e5+5;
int t,n,m,x,y,eg[N],cnt; bool vis[N];
int main()
{
for (scanf("%d",&t);t;--t)
{
RI i; for (scanf("%d%d",&n,&m),cnt=0,i=1;i<=m;++i)
scanf("%d%d",&x,&y),!vis[x]&&!vis[y]&&(vis[x]=vis[y]=1,eg[++cnt]=i);
if (cnt>=n)
{
puts("Matching"); for (i=1;i<=n;++i)
printf("%d%c",eg[i]," \n"[i==cnt]);
} else
{
puts("IndSet"); for (cnt=0,i=1;i<=3*n&&cnt<n;++i)
if (!vis[i]) printf("%d ",i),++cnt; putchar('\n');
}
for (i=1;i<=3*n;++i) vis[i]=0;
}
return 0;
}

D. Rectangle Painting 1

首先我们考虑两个显而易见的结论:

  1. 若一个子矩阵全为白显然无需染色
  2. 若一个子矩阵全为黑直接染完是最优的(即拆成小块永远没有直接染优)

那么我们把这两种情况作为DP的终止条件就可以DP了,设\(f_{x1,y1,x2,y2}\)表示\((x1,y1)-(x2,y2)\)的子矩阵全部染白的最小代价,转移的之后考虑断开行或列分割成两个更小的矩阵转移即可

记忆化搜索实现DP,二维前缀和处理下矩阵状态即可

#include<cstdio>
#include<cstring>
#include<iostream>
#define RI register int
#define CI const int&
using namespace std;
const int N=55;
int n,pt[N][N],f[N][N][N][N]; char ch;
inline void get_char(char& ch)
{
while (isspace(ch=getchar()));
}
inline int getpt(CI x1,CI y1,CI x2,CI y2)
{
return pt[x2][y2]-pt[x2][y1-1]-pt[x1-1][y2]+pt[x1-1][y1-1];
}
inline int DP(CI x1,CI y1,CI x2,CI y2)
{
if (~f[x1][y1][x2][y2]) return f[x1][y1][x2][y2];
if (getpt(x1,y1,x2,y2)==(x2-x1+1)*(y2-y1+1))
return f[x1][y1][x2][y2]=max(x2-x1+1,y2-y1+1);
if (!getpt(x1,y1,x2,y2)) return f[x1][y1][x2][y2]=0;
RI i; int ret=max(x2-x1+1,y2-y1+1);
for (i=x1;i<x2;++i) ret=min(ret,DP(x1,y1,i,y2)+DP(i+1,y1,x2,y2));
for (i=y1;i<y2;++i) ret=min(ret,DP(x1,y1,x2,i)+DP(x1,i+1,x2,y2));
return f[x1][y1][x2][y2]=ret;
}
int main()
{
RI i,j; for (scanf("%d",&n),i=1;i<=n;++i) for (j=1;j<=n;++j)
get_char(ch),pt[i][j]=pt[i-1][j]+pt[i][j-1]-pt[i-1][j-1]+(ch=='#');
return memset(f,-1,sizeof(f)),printf("%d",DP(1,1,n,n)),0;
}

E. Rectangle Painting 2

和上面一题类似,只不过把数据范围加大了,然后代价变成了取\(\min\)

又有一个显而易见的结论此时每次选择的都是一整行或一整列,代价为\(1\)

因此我们考虑将每个黑点的行节点向列节点连一条流量为\(\infty\)的边,然后从源点向行节点连流量为\(1\)的边,从列节点向汇点连流量为\(1\)的边,这样整张图的最小割即为答案(至少要割去一个黑点的行或列节点)

但是现在黑点给出的是一个矩阵的形式,这也很简单,我们将区间化为左开右闭,然后离散化一下,建图的时候源点到行节点连接这一段经过行的数目,到汇点的同理

然后跑一下最大流就是答案

#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=205,M=200005,INF=1e9;
int n,m,l1[N],r1[N],l2[N],r2[N],rstl[N],rstr[N],numl,numr;
struct edge
{
int to,nxt,v;
}e[M]; int head[N],cnt=1,s,t;
inline int findl(CI x)
{
return lower_bound(rstl+1,rstl+numl+1,x)-rstl;
}
inline int findr(CI x)
{
return lower_bound(rstr+1,rstr+numr+1,x)-rstr;
}
inline void addedge(CI x,CI y,CI v)
{
e[++cnt]=(edge){y,head[x],v}; head[x]=cnt;
e[++cnt]=(edge){x,head[y],0}; head[y]=cnt;
}
#define to e[i].to
class Network_Flow
{
private:
int q[N],dep[N],cur[N];
inline bool BFS(CI s,CI t)
{
RI H=0,T=1; memset(dep,0,t+1<<2); q[dep[s]=1]=s;
while (H<T)
{
int now=q[++H]; for (RI i=head[now];i;i=e[i].nxt)
if (e[i].v&&!dep[to]) dep[to]=dep[now]+1,q[++T]=to;
}
return dep[t];
}
inline int DFS(CI now,CI tar,int dis)
{
if (now==tar) return dis; int ret=0;
for (RI& i=cur[now];i;i=e[i].nxt)
if (e[i].v&&dep[to]==dep[now]+1)
{
int dist=DFS(to,tar,min(dis,e[i].v));
dis-=dist; ret+=dist; e[i].v-=dist; e[i^1].v+=dist;
}
if (ret) dep[now]=0; return ret;
}
public:
inline int Dinic(CI s,CI t,int ret=0)
{
while (BFS(s,t)) memcpy(cur,head,t+1<<2),ret+=DFS(s,t,INF); return ret;
}
}NF;
#undef to
int main()
{
RI i,j,k; for (scanf("%d%d",&n,&m),i=1;i<=m;++i)
scanf("%d%d%d%d",&l1[i],&r1[i],&l2[i],&r2[i]),
--l1[i],rstl[++numl]=l1[i],rstl[++numl]=l2[i],
--r1[i],rstr[++numr]=r1[i],rstr[++numr]=r2[i];
sort(rstl+1,rstl+numl+1); numl=unique(rstl+1,rstl+numl+1)-rstl-1;
sort(rstr+1,rstr+numr+1); numr=unique(rstr+1,rstr+numr+1)-rstr-1;
for (i=1;i<numl;++i) addedge(s,i,rstl[i+1]-rstl[i]);
for (t=numl+numr+1,i=1;i<numr;++i) addedge(numl+i,t,rstr[i+1]-rstr[i]);
for (i=1;i<=m;++i)
{
l1[i]=findl(l1[i]); r1[i]=findr(r1[i]);
l2[i]=findl(l2[i]); r2[i]=findr(r2[i]);
for (j=l1[i];j<l2[i];++j) for (k=r1[i];k<r2[i];++k)
addedge(j,numl+k,INF);
}
return printf("%d",NF.Dinic(s,t)),0;
}

F. GCD Groups 2

讲道理我并不知道这题正解是什么,当时开个玩笑写个随机就过了

考虑我们随机从未选取的数中选择一个数,如果这个数扔到第一个集合中可以使当前的\(\gcd\)变小就扔进去

然后剩下的数都放进第二个集合里,我们发现这样的正确性显然,因为加入的数越多\(\gcd\)一定不会变大

但是随机的正确率我并不会证,大致理解了一下就是要求一个集合内存在一个质因子能整除每个数\(\gcd\)才不为\(1\),由于数的分布比较均匀因此质因子分布也很均匀

所以我们直接随机做,然后卡时到\(0.45s\)的时候退出输\(NO\)即可

#include<cstdio>
#include<cstdlib>
#include<ctime>
#include<algorithm>
#define RI register int
#define CI const int&
using namespace std;
const int N=100005;
int n,p[N],a[N],g1,g2,tp; bool cs[N];
inline int gcd(CI n,CI m)
{
return m?gcd(m,n%m):n;
}
int main()
{
//freopen("F.in","r",stdin); freopen("F.out","w",stdout);
RI i; for (srand(20030909),scanf("%d",&n),i=1;i<=n;++i)
scanf("%d",&a[i]),p[i]=i; while (1.0*clock()/CLOCKS_PER_SEC<=0.45)
{
for (random_shuffle(p+1,p+n+1),g2=0,g1=a[p[1]],cs[p[1]]=1,i=2;i<=n;++i)
if (g1!=1&&(tp=gcd(g1,a[p[i]]))<g1) cs[p[i]]=1,g1=tp; else g2=gcd(g2,a[p[i]]);
if (g1==1&&g2==1)
{
for (puts("YES"),i=1;i<=n;++i) printf("%d ",cs[i]+1); exit(0);
}
for (i=1;i<=n;++i) cs[i]=0;
}
return puts("NO"),0;
}

Postscript

讲道理这场CF难度确实不大,不过也算是有挺多思维好题的吧

今后得多做做这样的比赛QWQ

Codeforces Round #576 (Div. 1)的更多相关文章

  1. Codeforces Round #576 (Div. 2) D. Welfare State

    http://codeforces.com/contest/1199/problem/D Examples input1 output1 input2 output2 Note In the firs ...

  2. Codeforces Round #576 (div.1 + div.2)

    Div2 A 长度为\(n(n≤10^5)\)的数组,每个元素不同,求有多少个位置\(d\)满足\(d - x \le j < d \And d < j \le d + y a_d< ...

  3. Codeforces Round #576 (Div. 1) 简要题解 (CDEF)

    1198 C Matching vs Independent Set 大意: 给定$3n$个点的无向图, 求构造$n$条边的匹配, 或$n$个点的独立集. 假设已经构造出$x$条边的匹配, 那么剩余$ ...

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

    比赛链接:https://codeforc.es/contest/1199 A. City Day 题意:给出一个数列,和俩个整数\(x,y\),要求找到序号最靠前的数字\(d\),使得\(d\)满足 ...

  5. [快速幂]Codeforces Round #576 (Div. 2)-C. MP3

    C. MP3 time limit per test 1 second memory limit per test 256 megabytes input standard input output ...

  6. Codeforces Round #366 (Div. 2) ABC

    Codeforces Round #366 (Div. 2) A I hate that I love that I hate it水题 #I hate that I love that I hate ...

  7. Codeforces Round #354 (Div. 2) ABCD

    Codeforces Round #354 (Div. 2) Problems     # Name     A Nicholas and Permutation standard input/out ...

  8. Codeforces Round #368 (Div. 2)

    直达–>Codeforces Round #368 (Div. 2) A Brain’s Photos 给你一个NxM的矩阵,一个字母代表一种颜色,如果有”C”,”M”,”Y”三种中任意一种就输 ...

  9. cf之路,1,Codeforces Round #345 (Div. 2)

     cf之路,1,Codeforces Round #345 (Div. 2) ps:昨天第一次参加cf比赛,比赛之前为了熟悉下cf比赛题目的难度.所以做了round#345连试试水的深浅.....   ...

随机推荐

  1. 修改centos服务器时区并同步最新时间

    rm -rf /etc/localtime ln -s /usr/share/zoneinfo/Asia/Shanghai /etc/localtime ntpdate cn.pool.ntp.org ...

  2. $.Ajax、$.Get、$.Post代码实例参数解析

    $.ajax 语法: $.ajax({name:value, name:value, ... }) 示例: $.ajax({ url: "/testJson", type: &qu ...

  3. C# 灵活切换开发/测试/生成环境web.config

    web.config <configuration> <connectionStrings configSource="config\Sit.db.config" ...

  4. Oracle - 数字处理 - 取上取整、向下取整、保留N位小数、四舍五入、数字格式化

    用oracle sql对数字进行操作: 取上取整.向下取整.保留N位小数.四舍五入.数字格式化 取整(向下取整): select floor(5.534) from dual; select trun ...

  5. 1-HTTPS之SNI介绍

    原文:https://blog.51cto.com/zengestudy/2170245 介绍 早期的SSLv2根据经典的公钥基础设施PKI(Public Key Infrastructure)设计, ...

  6. python3测试网站网速

    一.运行环境 1.Windows 10 2.python 3.8 二.安装第三方库pycurl 1.先安装 pip install wheel 2.在安装pycurl https://download ...

  7. SpringBoot打可执行war包

    1. 主程序类: @SpringBootApplication public class Application extends SpringBootServletInitializer { @Ove ...

  8. UITableView与UITableViewCell

    转自:http://blog.sina.com.cn/s/blog_4cd14afb01014j97.html UITableView用来以表格的形式显示数据.关于UITableView,我们应该注意 ...

  9. elasticsearch ik分词

    elasticsearch 默认并不支持中文分词,默认将每个中文字切分为一个词,这明显不符合我们的业务要求.这里就需要用到ik分词插件. 本文主要囊括了以下几部分,ik插件安装.ik用法介绍.自定义词 ...

  10. wpf DATAgrid模板中button 命令绑定以及命令参数绑定

    场景:视频上传功能,上传列表使用DataGrid控件,视频有不同的状态对应不同的操作,DataGrid中最后一列为操作列,里面是Button控件.希望点击Button后执行对应的操作,但是设置Butt ...