点此进入比赛

\(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. SDN课程阅读作业(2)

    SDN课程阅读作业(2) 1.过去20年中可编程网络的发展可以分为几个阶段?每个阶段的贡献是什么? 答:可编程网络的发展分为三个阶段. (1)主动网络阶段 贡献: 1.对主动网络的研究开创了可编程网络 ...

  2. php strlen和mb_strlen

    结果: 结论:如果没有中文,尽量使用strlen

  3. 通过组件实现相同group下字符串拼接

    实现效果 组件处理流程如下:         1 使用Sorter组件对ColA进行排序       2 使用expression组件进行如下配置 3 使用aggregate组件进行如下配置 ColA ...

  4. 划词标注1——使用svg绘制换行文本并自动识别库中字典数据

    业务需求 给出一段文本,自动识别出文本中包含的关键字信息,关键字是库里已知的数据,根据类型的不同显示出不同的颜色 业务分析 1)采用css:文本识别出来后,根据识别出的文本更改对应文本的dom,通过更 ...

  5. [反汇编] 获取上一个栈帧的ebp

    使用代码 lea ecx, [ebp+4+参数长度] 就可以实现. 如下图,理解栈帧的结构,很好理解. 虽然也是 push param的,但这部分在恢复时被调用函数会恢复的,因此这并不算esp的值. ...

  6. HashMap、ConcurrentHashMap解析

    一.HashMap分析 在JDK1.8之前,hashMap由数组+链表组成,1.8之后,对hashMap进行了一些修改,最大的不同就是利用了红黑树,所以其由数组+链表+红黑树组成.查找时,根据hash ...

  7. dependencies和devDependencies区别

    vue-cli3.x项目的package.json中,有两种依赖: dependencies:项目依赖.在编码阶段和呈现页面阶段都需要的,也就是说,项目依赖即在开发环境中,又在生产环境中.如js框架v ...

  8. Ubuntu的系统应用

    1:最近在苹果笔记本做了双系统,启动电脑后还是蛮酷的,但是ubuntu系统安好后,没有wifi图标,于是必须连接有线网络,更新数据包才可以. 2:      常用命令 查看软件xxx安装内容#dpkg ...

  9. JavaScript之找LHS查询和RHS查询

    LHS和RHS,当变量出现在赋值操作的左侧时进行LHS 查询,出现在右侧时进行RHS 查询. LHS 查询是试图找到变量的容器本身,从而可以对其赋值. RHS 理解成retrieve his sour ...

  10. Django 全局log process_exception中间件

    class BaseResp: # 基础的返回值类 def __init__(self, code, msg, data): self.code = code self.msg = msg self. ...