点此进入比赛

\(A\):MP3(点此看题面

大致题意: 让你选择一个值域区间\([L,R]\),使得序列中满足\(L\le a_i\le R\)的数的种类数不超过\(2^{\lfloor\frac {8I}n\rfloor}\),输出剩余数的数量的最小值。

对着英文题面懵了半天。。。

理解题意之后这题就很水了。

考虑我们先排序+离散化,然后选择的数必然是离散化序列上的一段长度为\(2^{\lfloor\frac {8I}n\rfloor}\)的区间。

那么我们枚举区间左端点,双指针维护区间右端点,就可以求出答案了。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 400000
#define INF 1e9
#define Gmin(x,y) (x>(y)&&(x=(y)))
using namespace std;
int n,m,t,a[N+5],s[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
char c,*A,*B,FI[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
}F;
int main()
{
RI i,p1,p2,ans=INF;for(F.read(n,m),i=1;i<=n;++i) F.read(a[i]);//读入
for(sort(a+1,a+n+1),i=1;i<=n;++i) s[i]=a[i];t=unique(s+1,s+n+1)-s-1;//排序+离散化
if(m=8*m/n,m>=30) return puts("0"),0;if(m=(1LL<<m),m>t) return puts("0"),0;//若能选择的区间长度超过总长度,直接输出0
for(p1=p2=i=1;i+m-1<=t;++i)//枚举左端点
{
W(p1^n&&a[p1]<s[i]) ++p1;W(p2^n&&a[p2+1]<=s[i+m-1]) ++p2;//双指针维护原序列上的区间
Gmin(ans,(p1-1)+(n-p2));//更新答案
}return printf("%d",ans),0;//输出答案
}

\(B\):Welfare State(点此看题面

大致题意: 支持两种操作,单点修改,全序列对一个数取\(Max\),求最后的序列。

我写了一个线段树。

我们用\(Mx_{rt}\)表明\(rt\)子树内所有数都要向它取\(Max\),然后当要对\(rt\)子树内的值进行单点修改时,就把\(Mx_{rt}\)下传给左右儿子。

最后每个位置的答案就是其在线段树中对应的叶节点的值与其到根路径上所有\(Mx_{rt}\)的最大值。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 200000
using namespace std;
int n,a[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void write(Con Ty& x,Con char& y) {write(x),pc(y);}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
template<int SZ> class SegmentTree//线段树
{
private:
#define LT l,mid,rt<<1
#define RT mid+1,r,rt<<1|1
#define PD(x) (U(x<<1,Mx[x]),U(x<<1|1,Mx[x]),Mx[x]=0)
#define U(x,v) (Mx[x]<(v)&&(Mx[x]=v))
int n,V[SZ+5],Mx[SZ<<2];
I void Upt(CI x,CI y,CI l,CI r,CI rt)//单点修改
{
if(l==r) return (void)(Mx[rt]=0);RI mid=l+r>>1;PD(rt),
x<=mid?Upt(x,y,LT):Upt(x,y,RT);
}
I int Qry(CI x,CI l,CI r,CI rt)//单点查询
{
if(l==r) return max(V[l],Mx[rt]);RI mid=l+r>>1,t;
return t=x<=mid?Qry(x,LT):Qry(x,RT),max(t,Mx[rt]);
}
public:
I void Build(CI _n,int *a) {n=_n;for(RI i=1;i<=n;++i) V[i]=a[i];}
I void Upt(CI x,CI y) {V[x]=y,Upt(x,y,1,n,1);}I void Max(CI x) {U(1,x);}
I int Qry(CI x) {return Qry(x,1,n,1);}
};SegmentTree<N> S;
int main()
{
RI Qt,i,op,x,y;for(F.read(n),i=1;i<=n;++i) F.read(a[i]);S.Build(n,a);//初始化
F.read(Qt);W(Qt--) F.read(op,x),op==1?(F.read(y),S.Upt(x,y)):S.Max(x);//处理操作
for(i=1;i<=n;++i) F.write(S.Qry(i)," \n"[i==n]);return F.clear(),0;//输出序列
}

\(C\):Matching vs Independent Set(点此看题面

大致题意: 给你一张\(3n\)个点和\(m\)条边的图,求一个\(n\)条边的匹配或\(n\)个点的独立集。

这题的做法很巧妙啊。

考虑我们先对每条边扫一遍,只要它的两个端点都未曾作为某个匹配的端点,就把这条边作为一个匹配。

然后,如果作为匹配的边数大于等于\(n\),就直接输出其中的\(n\)条边。

否则,作为匹配的点数显然小于\(2n\),也就是说,剩下的点数大于\(n\)。而剩下的点两两之间,显然都没有边相连,否则就会被抓去作为匹配。所以输出其中\(n\)个点即可。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define M 500000
using namespace std;
int n,m,s[3*N+5],ans[M+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void write(Con Ty& x,Con char& y) {write(x),pc(y);}
I void writes(Con string& s) {for(RI i=0,l=s.length();i^l;++i) pc(s[i]);}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
int main()
{
RI Tt,i,t,x,y;F.read(Tt);W(Tt--)
{
for(F.read(n,m),i=1;i<=3*n;++i) s[i]=0;//清空
for(t=0,i=1;i<=m;++i) F.read(x,y),!s[x]&&!s[y]&&(s[x]=s[y]=1,ans[++t]=i);//若能作为匹配就作为匹配
if(t>=n) for(F.writes("Matching\n"),i=1;i<=n;++i) F.write(ans[i]," \n"[i==n]);//若存在匹配
else for(F.writes("IndSet\n"),t=0,i=1;i<=3*n&&t^n;++i) !s[i]&&(F.write(i," \n"[++t==n]),0);//否则存在独立集
}return F.clear(),0;
}

\(D\):Rectangle Painting 1(点此看题面

大致题意: 给你一个方阵,其中有一些格子被染黑,每次可以选择一个\(w*h\)的区间以\(max(w,h)\)的代价将其染黑,求最小代价将整个方阵染白。

\(n\)很小,想到暴力\(DP\)。

设\(f_{xx,yx,xy,yy}\)表示将以\((xx,yx)\)为左上角、\((xy,yy)\)为右下角的区间全染白的最小代价。

可以以\(dfs\)形式转移,每次枚举一行或一列,将这个区间分裂转移。

由于有记忆化,跑满也只是\(O(n^5)\)的。而且其中有些区间是不合法的,并且当一个区间全白或全黑的时候我们可以直接返回答案,所以跑不满,是能过的。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 50
using namespace std;
int n,a[N+5][N+5],s[N+5][N+5],f[N+5][N+5][N+5][N+5];
I int DP(CI xx,CI yx,CI xy,CI yy)//求将当前区间染白的最小代价
{
if(f[xx][yx][xy][yy]) return f[xx][yx][xy][yy];RI i,t,res=max(xy-xx+1,yy-yx+1);//如果访问过
if(t=s[xy][yy]-s[xx-1][yy]-s[xy][yx-1]+s[xx-1][yx-1],!t) return 0;if(t==(xy-xx+1)*(yy-yx+1)) return res;//如果全白或全黑
for(i=xx;i^xy;++i) t=DP(xx,yx,i,yy)+DP(i+1,yx,xy,yy),res>t&&(res=t);//枚举一行分裂
for(i=yx;i^yy;++i) t=DP(xx,yx,xy,i)+DP(xx,i+1,xy,yy),res>t&&(res=t);return f[xx][yx][xy][yy]=res;//枚举一列分裂
}
int main()
{
RI i,j;string st;for(scanf("%d",&n),i=1;i<=n;++i)
for(cin>>st,j=1;j<=n;++j) a[i][j]=st[j-1]=='#',
s[i][j]=s[i-1][j]+s[i][j-1]-s[i-1][j-1]+a[i][j];//预处理二维前缀和
return printf("%d",DP(1,1,n,n)),0;
}

\(E\):Rectangle Painting 2(点此看题面

大致题意: 给你一个方阵,其中有一些区间被染黑,每次可以选择一个\(w*h\)的区间以\(min(w,h)\)的代价将其染黑,求最小代价将整个方阵染白。

由于是\(min(w,h)\),所以贪心考虑,我们每次必然染白一行或者一列。

这就变成了一个经典的二分图匹配问题。

我们对于黑色格子\((i,j)\),由第\(i\)行向第\(j\)列连一条容量为\(INF\)的边。

由超级源向每行连边,由每列向超级汇连边,然后跑最大流即可。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define M 50
#define INF 2e9
using namespace std;
int n,m,xx[M+5],xy[M+5],yx[M+5],yy[M+5],v[2*M+5][2*M+5];
class Discretization//离散化
{
private:
int s[2*M+5];
public:
int n;I void Ins(CI x) {s[++n]=x;}I void Init() {sort(s+1,s+n+1),n=unique(s+1,s+n+1)-s-1;}
I int GV(CI x) {return lower_bound(s+1,s+n+1,x)-s;}I int GF(CI x) {return s[x];}
}Dx,Dy;
template<int PS,int ES> class Dinic//最大流
{
private:
#define Else(x) ((((x)-1)^1)+1)
#define add(x,y,f) (e[++ee].nxt=lnk[x],e[lnk[x]=ee].to=y,e[ee].F=f)
int ee,lnk[PS+5],cur[PS+5],q[PS+5],dep[PS+5];struct edge {int to,nxt,F;}e[2*ES+5];
I bool BFS(CI s,CI t)//BFS找增广路
{
RI i,k,H=1,T=0;for(i=1;i<=Dx.n+Dy.n+2;++i) dep[i]=0;dep[q[++T]=s]=1;
W(H<=T&&!dep[t]) for(i=lnk[k=q[H++]];i;i=e[i].nxt)
e[i].F&&!dep[e[i].to]&&(dep[q[++T]=e[i].to]=dep[k]+1);
return dep[t];
}
I int DFS(CI x,RI f)//DFS求最大流
{
if(x==T||!f) return f;RI& i=cur[x];RI t,res=0;for(;i;i=e[i].nxt)
{
if((dep[x]+1)^dep[e[i].to]||!e[i].F||!(t=DFS(e[i].to,min(f,e[i].F)))) continue;
if(e[i].F-=t,e[Else(i)].F+=t,res+=t,!(f-=t)) return res;
}return dep[x]=-1,res;
}
public:
int S,T;I Dinic() {S=1,T=2;}I int P1(CI x) {return x+2;}I int P2(CI x) {return x+Dx.n+2;}
I void Add(CI x,CI y,CI f) {add(x,y,f),add(y,x,0);}//连边
I void Solve()
{
RI i,f=0;W(BFS(S,T)) {for(i=1;i<=Dx.n+Dy.n+2;++i) cur[i]=lnk[i];f+=DFS(S,INF);}//最大流
printf("%d",f);//输出答案
}
};Dinic<4*M+2,4*M+4*M*M> D;
int main()
{
RI i,j,k;scanf("%d%d",&n,&m);
for(i=1;i<=m;++i) scanf("%d%d%d%d",xx+i,yx+i,xy+i,yy+i),//读入
Dx.Ins(xx[i]),Dx.Ins(++xy[i]),Dy.Ins(yx[i]),Dy.Ins(++yy[i]);
for(Dx.Ins(n+1),Dy.Ins(n+1),Dx.Init(),Dy.Init(),i=1;i<=m;++i)//对于每个黑色区间
{
xx[i]=Dx.GV(xx[i]),yx[i]=Dy.GV(yx[i]),xy[i]=Dx.GV(xy[i])-1,yy[i]=Dy.GV(yy[i])-1;//求出离散化后的值
for(j=xx[i];j<=xy[i];++j) for(k=yx[i];k<=yy[i];++k) ++v[j][k];//每行向每列连边
}
for(i=1;i^Dx.n;++i) for(j=1;j^Dy.n;++j) v[i][j]&&(D.Add(D.P1(i),D.P2(j),INF),0);//连边
for(i=1;i^Dx.n;++i) D.Add(D.S,D.P1(i),Dx.GF(i+1)-Dx.GF(i));
for(i=1;i^Dy.n;++i) D.Add(D.P2(i),D.T,Dy.GF(i+1)-Dy.GF(i));return D.Solve(),0;
}

\(F\):GCD Groups 2(点此看题面

大致题意: 让你把一组数分成两组,使每组\(gcd\)都为\(1\)。

随机+卡时大法好。

我们每次随机一个排列,然后枚举每一个数。贪心地想,若这个数加到第一组内,能使第一组的\(gcd\)减少,我们就把这个数加到第一组中,否则加到第二组中。

最后看下是否两组\(gcd\)都为\(1\),若为\(1\),就可以直接输出当前方案了。

如果直到\(0.49\)秒都没有得出答案,就可以输出无解了。

#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
using namespace std;
int n,a[N+5],s[N+5],p[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C==E&&(clear(),0),*C++=c)
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T;char c,*A,*B,*C,*E,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI,C=FO,E=FO+FS;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Tp I void write(Con Ty& x,Con char& y) {write(x),pc(y);}
I void clear() {fwrite(FO,1,C-FO,stdout),C=FO;}
}F;
I int gcd(CI x,CI y) {return y?gcd(y,x%y):x;}
int main()
{
RI i,t,g1,g2;for(F.read(n),i=1;i<=n;++i) F.read(a[i]),s[i]=i;
W(1.0*clock()/CLOCKS_PER_SEC<=0.49)//卡时
{
random_shuffle(s+1,s+n+1),g1=a[s[1]],p[s[1]]=1,g2=a[s[2]],p[s[2]]=0;//随机排列
for(i=3;i<=n;++i) (t=gcd(g1,a[s[i]]))<g1?(g1=t,p[s[i]]=1):(g2=gcd(g2,a[s[i]]),p[s[i]]=0);//贪心分组
if(g1==1&&g2==1) {for(puts("YES"),i=1;i<=n;++i) F.write(p[i]+1,' ');return F.clear(),0;}//若合法直接输出
}return puts("NO"),0;//输出无解
}

【CodeForces】CodeForcesRound576 Div1 解题报告的更多相关文章

  1. 【CodeForces】CodeForcesRound594 Div1 解题报告

    点此进入比赛 \(A\):Ivan the Fool and the Probability Theory(点此看题面) 大致题意: 给一个\(n\times m\)的矩阵\(01\)染色,使得不存在 ...

  2. codeforces 31C Schedule 解题报告

    题目链接:http://codeforces.com/problemset/problem/31/C 题目意思:给出 n 个 lessons 你,每个lesson 有对应的 起始和结束时间.问通过删除 ...

  3. codeforces 499B.Lecture 解题报告

    题目链接:http://codeforces.com/problemset/problem/499/B 题目意思:给出两种语言下 m 个单词表(word1, word2)的一一对应,以及 profes ...

  4. codeforces 495C. Treasure 解题报告

    题目链接:http://codeforces.com/problemset/problem/495/C 题目意思:给出一串只有三种字符( ')','(' 和 '#')组成的字符串,每个位置的这个字符 ...

  5. codeforces 490B.Queue 解题报告

    题目链接:http://codeforces.com/problemset/problem/490/B 题目意思:给出每个人 i 站在他前面的人的编号 ai 和后面的人的编号 bi.注意,排在第一个位 ...

  6. CodeForces 166E -Tetrahedron解题报告

    这是本人写的第一次博客,学了半年的基础C语言,初学算法,若有错误还请指正. 题目链接:http://codeforces.com/contest/166/problem/E E. Tetrahedro ...

  7. codeforces 489A.SwapSort 解题报告

    题目链接:http://codeforces.com/problemset/problem/489/A 题目意思:给出一个 n 个无序的序列,问能通过两两交换,需要多少次使得整个序列最终呈现非递减形式 ...

  8. codeforces 485A.Factory 解题报告

    题目链接:http://codeforces.com/problemset/problem/485/A 题目意思:给出 a 和 m,a 表示第一日的details,要求该日结束时要多生产 a mod ...

  9. codeforces 483A. Counterexample 解题报告

    题目链接:http://codeforces.com/problemset/problem/483/A 题目意思:给出一个区间 [l, r],要从中找出a, b, c,需要满足 a, b 互质,b, ...

随机推荐

  1. LVS 负载均衡——直接路由模式DR

    一.配置的网络拓扑结构图 二.配置lvs服务器 配置虚拟网卡地址(VIP地址) [root@localhost ~]# ifconfig eno16777728: 192.168.200.253 ne ...

  2. HTML连载52-网易注册界面之上部完成、中部初探

    一.看一下注释即可,都是前面学到的知识,然后进行整合完成网页的制作,未完待续,这个网易界面跨度可大三天. <!DOCTYPE html> <html lang="en&qu ...

  3. selenium常用的三种等待方式

    一.强制等待 使用方法:sleep(X),等待X秒后,进行下一步操作. 第一种也是使用最简单的一种办法就是强制等待sleep(X),强制让浏览器等待X秒,不管当前操作是否完成,是否可以进行下一步操作, ...

  4. Selenium+java - 关于富文本编辑器的处理

    什么是富文本编辑器? 富文本编辑器,Rich Text Editor, 简称 RTE, 是一种可内嵌于浏览器,所见即所得的文本编辑器.具体长啥样,如下图: 通过自动化操作富文本编辑器 模拟场景:在富文 ...

  5. 拎壶学python3-----(2)python之if语句用法

    在生活中我们经常遇到各种选择,比如玩色子,猜大小,再比如选择未来另一半.python也经常会遇到这样的选择,这时候if语句显得尤为重要. 下边我们看一个简单的例子 如果是二选一怎么做呢?如下 如果多个 ...

  6. Nginx超时设定

    最近针对公司的goscon网关发了一个PR,新增了握手阶段的超时判定.现在回顾一下Nginx的所有超时判定,看看目前还缺少哪些判定 ngx_http_core_module包含的timeout: cl ...

  7. MySQL-8.0.18 引入了破坏性变更

    MySQL-8.0.18 引入了破坏性变更 变更日志里面有这样一项 When the server is run with --initialize, there is no reason to lo ...

  8. 手写SpringMVC实现过程

    1. Spring Boot,Spring MVC的底层实现都是Servlet的调用. 2. Servlet的生命周期里面首先是类的初始化,然后是类的方法的调用,再次是类的销毁. 3. 创建一个spr ...

  9. 关于WIN7下IE8IE7浏览器无法安装微信支付商户证书的解决方案

    关于WIN7下IE8IE7浏览器无法安装微信支付商户证书的解决方案 解决方案就是使用 chrome浏览器 默认的chorme浏览器  打开微信商户平台 会提示让安装控件  然后反复安装 其实要解决这个 ...

  10. SPA项目开发登陆注册

    使用vue-cli脚手架工具创建一个vue项目 vue init webpack pro01 npm安装elementUI cd pro01 #进入新建项目的根目录 安装: npm install a ...