【CodeForces】CodeForcesRound576 Div1 解题报告

$A$：MP3（点此看题面）

#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 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);}
}F;
int main()
{
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（点此看题面）

#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 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);}
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()
{
for(i=1;i<=n;++i) F.write(S.Qry(i)," \n"[i==n]);return F.clear(),0;//输出序列
}

$C$：Matching vs Independent Set（点此看题面）

#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 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);}
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()
{
{
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（点此看题面）

$n$很小，想到暴力$DP$

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

#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（点此看题面）

#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)
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 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];//每行向每列连边
}
}

$F$：GCD Groups 2（点此看题面）

#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 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);}
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()
{
}