P15093 [UOI 2025 II Stage] Odd Rows题解

P15093 [UOI 2025 II Stage] Odd Rows

题目描述

一次,s1mple 找到了著名的问题解决者 Kostya,对他说:

如果你想变得更强,就需要持续练习。这里有一个用于训练的问题:

给定一个大小为 n×mn \times mn×m 的矩阵 aaannn 为行数,mmm 为列数),其中每个元素要么是 000,要么是 111。已知每列恰好包含 cic_ici111。每列内的元素可以自由排列。目标是最大化包含奇数个 111 的行数,并找出这样的一个矩阵。

Kostya 默默点头,坐到桌边开始工作,深知每一次练习都让他更接近精通。

Kostya 没能解决这个问题,现在请你帮他解决它。

如果你只找出数量而不输出矩阵,可以获得部分分数。详情见下文。

输入格式

  • 第一行包含两个整数 nnnmmm1≤n⋅m≤1061 \le n \cdot m \le 10^61nm106)——矩阵的维度。
  • 第二行包含 mmm 个整数 c1,c2,…,cmc_1, c_2, \dots, c_mc1,c2,,cm0≤ci≤n0 \le c_i \le n0cin)——每列中 111 的数量。

输出格式

  • 第一行输出一个整数 ttt0≤t≤n0 \leq t \leq n0tn)——矩阵中具有奇数和的行数。
  • 接下来的 nnn 行,每行输出 mmm 个整数 aija_{ij}aij0≤aij≤10 \leq a_{ij} \leq 10aij1)——矩阵的元素。

输入输出样例 #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,m5
  • 888 分):矩阵中 111 的总数不超过 nnn
  • 202020 分):每列中 111 的数量不超过 n/2n/2n/2
  • 141414 分):n,m≤50n, m \le 50n,m50
  • 141414 分):n≤3 000n \le 3\,000n3000
  • 141414 分):n⋅m≤3⋅105n \cdot m \le 3\cdot10^5nm3105
  • 202020 分):无额外限制。

对于每个测试组,如果你为该组中每个测试输出了正确的 ttt,你可以获得该组一半的分数。

注意,要获得部分分数,你需要输出正确的 ttt 并且:

  • 要么不输出其他内容,即只输出 ttt,不输出矩阵;
  • 要么输出一个完整的由 000111 组成的矩阵,该矩阵不必正确。例如,可以是一个全零矩阵。

如果你只输出部分行、或输出过多行、或输出非 000111 的数字等,你将获得 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;
}
posted @ 2026-01-28 21:12  bz02_2023f2  阅读(8)  评论(0)    收藏  举报  来源