P15093 [UOI 2025 II Stage] Odd Rows题解
P15093 [UOI 2025 II Stage] Odd Rows
题目描述
一次,s1mple 找到了著名的问题解决者 Kostya,对他说:
如果你想变得更强,就需要持续练习。这里有一个用于训练的问题:
给定一个大小为 n×mn \times mn×m 的矩阵 aaa(nnn 为行数,mmm 为列数),其中每个元素要么是 000,要么是 111。已知每列恰好包含 cic_ici 个 111。每列内的元素可以自由排列。目标是最大化包含奇数个 111 的行数,并找出这样的一个矩阵。
Kostya 默默点头,坐到桌边开始工作,深知每一次练习都让他更接近精通。
Kostya 没能解决这个问题,现在请你帮他解决它。
如果你只找出数量而不输出矩阵,可以获得部分分数。详情见下文。
输入格式
- 第一行包含两个整数 nnn 和 mmm(1≤n⋅m≤1061 \le n \cdot m \le 10^61≤n⋅m≤106)——矩阵的维度。
- 第二行包含 mmm 个整数 c1,c2,…,cmc_1, c_2, \dots, c_mc1,c2,…,cm(0≤ci≤n0 \le c_i \le n0≤ci≤n)——每列中 111 的数量。
输出格式
- 第一行输出一个整数 ttt(0≤t≤n0 \leq t \leq n0≤t≤n)——矩阵中具有奇数和的行数。
- 接下来的 nnn 行,每行输出 mmm 个整数 aija_{ij}aij(0≤aij≤10 \leq a_{ij} \leq 10≤aij≤1)——矩阵的元素。
输入输出样例 #1
输入 #1
8 4
6 1 6 1
输出 #1
6
1 1 1 0
1 0 1 1
1 0 1 0
1 0 1 0
1 0 0 0
1 0 0 0
0 0 1 0
0 0 1 0
输入输出样例 #2
输入 #2
4 4
3 0 3 0
输出 #2
2
1 0 1 0
1 0 1 0
1 0 0 0
0 0 1 0
输入输出样例 #3
输入 #3
7 3
4 3 2
输出 #3
7
1 1 1
1 0 0
1 0 0
1 0 0
0 1 0
0 1 0
0 0 1
说明/提示
在第一个示例中,第一列和第三列至少在 444 个位置相交,这意味着如果只有这两列,我们将有 444 个偶数和行。但由于还有两列各有一个 111,我们可以将其中两行转换为奇数和,因此最优答案是 666 个奇数和行。
在第二个示例中,我们可以忽略第二列和第四列,因为它们没有 111,这意味着它们不会改变任何行的奇偶性。第一列和第三列至少在 222 行相交,意味着至少有 222 行是偶数和,因此答案是 222。
在第三个示例中,答案是 777,因为存在一个满足条件且具有 777 个奇数和行的矩阵,并且不存在多于 777 个奇数和行的矩阵。
评分细则
- (101010 分):n,m≤5n, m \le 5n,m≤5;
- (888 分):矩阵中 111 的总数不超过 nnn;
- (202020 分):每列中 111 的数量不超过 n/2n/2n/2;
- (141414 分):n,m≤50n, m \le 50n,m≤50;
- (141414 分):n≤3 000n \le 3\,000n≤3000;
- (141414 分):n⋅m≤3⋅105n \cdot m \le 3\cdot10^5n⋅m≤3⋅105;
- (202020 分):无额外限制。
对于每个测试组,如果你为该组中每个测试输出了正确的 ttt,你可以获得该组一半的分数。
注意,要获得部分分数,你需要输出正确的 ttt 并且:
- 要么不输出其他内容,即只输出 ttt,不输出矩阵;
- 要么输出一个完整的由 000 和 111 组成的矩阵,该矩阵不必正确。例如,可以是一个全零矩阵。
如果你只输出部分行、或输出过多行、或输出非 000 非 111 的数字等,你将获得 000 分。
翻译由 DeepSeek V3 完成
思路
一道构造,DP的题,用线段树维护DP即可。
代码见下
#include<bits/stdc++.h>
using namespace std;
long long n,m,c[1000006],b[1000006],t1[3000006],t2[3000006],gcc[1000006];
struct one{
long long a,i;
}a[1000006];
bool cmp(one a1,one b1){
return a1.a<b1.a;
}
vector<vector<long long>> f,f2,v;
vector<long long> v1,v2;
long long te[4000006],lz[4000006],te2[4000006],lz2[4000006];
void alz(long long a1,long long v){
te[a1]=v;
lz[a1]=v;
}
void dow(long long a1){
if(lz[a1]!=0){
alz(a1*2,lz[a1]);
alz(a1*2+1,lz[a1]);
}
lz[a1]=0;
}
void bu(long long a1,long long l,long long r){
lz[a1]=0;
if(l==r){
te[a1]=0;
return ;
}
long long mid=(l+r)/2;
bu(a1*2,l,mid);
bu(a1*2+1,mid+1,r);
te[a1]=te[a1*2];
return ;
}
void ci(long long a1,long long l,long long r,long long x,long long y,long long v){
if(l>=x&&r<=y){
alz(a1,v);
return ;
}
long long mid=(l+r)/2;
dow(a1);
if(x<=mid){
ci(a1*2,l,mid,x,y,v);
}
if(mid+1<=y){
ci(a1*2+1,mid+1,r,x,y,v);
}
te[a1]=te[a1*2];
return ;
}
long long co(long long a1,long long l,long long r,long long x){
if(x<=l&&r<=x){
return te[a1];
}
long long mid=(l+r)/2;
long long dbdb=0;
dow(a1);
if(mid>=x){
dbdb+=co(a1*2,l,mid,x);
}
if(mid+1<=x){
dbdb+=co(a1*2+1,mid+1,r,x);
}
return dbdb;
}
void alz2(long long a1,long long v){
te2[a1]=v;
lz2[a1]=v;
}
void dow2(long long a1){
if(lz2[a1]!=0){
alz2(a1*2,lz2[a1]);
alz2(a1*2+1,lz2[a1]);
}
lz2[a1]=0;
}
void bu2(long long a1,long long l,long long r){
lz2[a1]=0;
if(l==r){
te2[a1]=0;
return ;
}
long long mid=(l+r)/2;
bu2(a1*2,l,mid);
bu2(a1*2+1,mid+1,r);
te2[a1]=te2[a1*2];
return ;
}
void ci2(long long a1,long long l,long long r,long long x,long long y,long long v){
if(l>=x&&r<=y){
alz2(a1,v);
return ;
}
long long mid=(l+r)/2;
dow2(a1);
if(x<=mid){
ci2(a1*2,l,mid,x,y,v);
}
if(mid+1<=y){
ci2(a1*2+1,mid+1,r,x,y,v);
}
te2[a1]=te2[a1*2];
return ;
}
long long co2(long long a1,long long l,long long r,long long x){
if(x<=l&&r<=x){
return te2[a1];
}
long long mid=(l+r)/2;
long long dbdb=0;
dow2(a1);
if(mid>=x){
dbdb+=co2(a1*2,l,mid,x);
}
if(mid+1<=x){
dbdb+=co2(a1*2+1,mid+1,r,x);
}
return dbdb;
}
int main(){
cin>>n>>m;
v.resize(n+2);
f.resize(m+2);
f2.resize(m+2);
for(int i=0;i<=n;i++){
v[i].resize(m+2);
}
for(int i=0;i<=m;i++){
f[i].resize(n+2);
f2[i].resize(n+2);
}
for(int i=1;i<=m;i++){
cin>>c[i];
a[i]=(one){c[i],i};
}
sort(a+1,a+m+1,cmp);
f[0][0]=1;
for(int i=1,rs[2];i<=m;i++){
rs[0]=rs[1]=n;
bu(1,0,n);
bu2(1,0,n);
for(int j=0;j<=n;j++){
t1[j]=t2[j]=0;
}
for(int j=0;j<=n;j++){
if(f[i-1][j]==1){
//rs=0;
if((j+c[i])%2==1){
if(max({0ll,c[i]-(n-j)})<=min((long long)j,c[i])){
ci(1,0,n,max(0ll,j+c[i]-2*min((long long)j,c[i])),min(n,j+c[i]-2*max({0ll,c[i]-(n-j)})),j);
t1[max(0ll,j+c[i]-2*min((long long)j,c[i]))]++;
t1[min(n+1,j+c[i]-2*max({0ll,c[i]-(n-j)})+1)]--;
}
}
else{
if(max({0ll,c[i]-(n-j)})<=min((long long)j,c[i])){
ci2(1,0,n,max(0ll,j+c[i]-2*min((long long)j,c[i])),min(n,j+c[i]-2*max({0ll,c[i]-(n-j)})),j);
t2[max(0ll,j+c[i]-2*min((long long)j,c[i]))]++;
t2[min(n+1,j+c[i]-2*max({0ll,c[i]-(n-j)})+1)]--;
}
}
// for(int k=max(0ll,c[i]-(n-j));k<=min((long long)j,c[i]);k++){
// f[i][j-k+c[i]-k]=1;
// }
}
}
for(int j=1;j<=n;j++){
t1[j]+=t1[j-1];
t2[j]+=t2[j-1];
}
for(int j=0;j<=n;j++){
if(j%2==1){
if(t1[j]>=1){
f[i][j]=1;
f2[i][j]=co(1,0,n,j);
}
}
else{
if(t2[j]>=1){
f[i][j]=1;
f2[i][j]=co2(1,0,n,j);
}
}
}
}
for(int i=n;i>=0;i--){
if(f[m][i]==1){
cout<<i<<endl;
for(int j=m,k=i;j>=1;k=f2[j][k],j--){
gcc[j]=k;
//cout<<j<<" "<<k<<endl;
}
for(int j=1,js=0,ju=0;j<=m;j++){
js=(c[j]+gcc[j-1]-gcc[j])/2;
ju=c[j]-js;
//cout<<js<<" "<<ju<<endl;
for(int k=1;k<=n;k++){
if(b[k]==1&&js>=1){
js--;
b[k]=0;
v[k][j]=1;
}
else if(b[k]==0&&ju>=1){
ju--;
b[k]=1;
v[k][j]=1;
}
}
}
for(int j=1;j<=n;j++){
for(int k=1;k<=m;k++){
cout<<v[j][k]<<" ";
}
cout<<endl;
}
return 0;
}
}
return 0;
}

浙公网安备 33010602011771号