题解 P6441 [COCI2011-2012#6] PASTELE
算法分析:二分+前缀和
答案的二分性是比较明显的,关注 “最大值”“最小值” 就可以看出来。因此最外层二分答案。
为了表述方便,记最大的颜色参数为 \(col\)。
注意到 \(0\le R_x,G_x,B_x\le256\),范围较小,在没有思路的情况下可以直接 \(col^3\) 枚举三者的最大值,然后再 \(\mathcal{O}(n)\) 判断可行性。总体复杂度为 \(\mathcal{O}(n\times col^3 \times \log_2(col))\)。预计得分 \(50pts\)。
那么如何优化?外层二分无法优化,枚举 \(col\) 的范围也只能有常数级别的优化,因此考虑优化掉 \(\mathcal{O}(n)\) 的可行性检查。
当我们知道 \(R_x,G_x,B_x\) 的范围时,是否可以考虑用前缀和 \(\mathcal{O}(1)\) 算出符合范围的蜡笔数?当然可以。考虑使用三维前缀和,用 \(f_{i,j,k}\) 表示满足 \(R_x\le i,G_x\le j,B_x\le k\) 的蜡笔总数。我们类比二维前缀和,利用容斥原理计算三维前缀和,遵循 “奇加偶减” 原则,即:
\[f_{i,j,k}=f_{i,j,k}+f_{i-1,j,k}+f_{i,j-1,k}+f_{i,j,k-1}-f_{i-1,j-1,k}-f_{i-1,j,k-1}-f_{i,j-1,k-1}+f_{i-1,j-1,k-1}
\]
于是可以 \(\mathcal{O}(1)\) 计算出符合条件的蜡笔数量。
总时间复杂度 \(\mathcal{O}(col^3 \times \log_2(col))\)。
注意:颜色存在 "0",输入时应将所有的编号加 \(1\),便于前缀和处理。相应的,输出时应将所有编号减 \(1\)。
code:
#include<bits/stdc++.h>
#define reg register
#define F(i,a,b) for(reg int i=a;i<=b;++i)
using namespace std;
inline int read();
const int N=1e5+1,M=260;
int n,k,ans=1e9;
int f[M][M][M];
struct P {
int r,g,b;
inline void inp() {
r=read()+1,g=read()+1,b=read()+1;
//由于颜色存在 0 前缀和不易处理,因此+1
}
} a[N],Mx,Mi,rec;
inline P max(P a,P b) {
return (P) {
max(a.r,b.r),max(a.g,b.g),max(a.b,b.b)
};
}
inline P min(P a,P b) {
return (P) {
min(a.r,b.r),min(a.g,b.g),min(a.b,b.b)
};
}
inline void init() {
F(i,1,n)++f[a[i].r][a[i].g][a[i].b];
F(i,1,257) {
F(j,1,257) {
F(k,1,257) {
f[i][j][k]+=f[i-1][j][k]+f[i][j-1][k]+f[i][j][k-1]
-f[i-1][j-1][k]-f[i-1][j][k-1]-f[i][j-1][k-1]
+f[i-1][j-1][k-1];
}
}
}//统计三维前缀和
}
inline bool check(int col) {
//一点枚举边界小优化
F(r,Mi.r,Mx.r) {
F(g,Mi.g,Mx.g) {
F(b,Mi.b,Mx.b) {
reg int lr=max(1,r-col),lg=max(1,g-col),lb=max(1,b-col);
reg int s=f[r][g][b]-f[lr-1][g][b]-f[r][lg-1][b]-f[r][g][lb-1]
+f[lr-1][lg-1][b]+f[lr-1][g][lb-1]+f[r][lg-1][lb-1]
-f[lr-1][lg-1][lb-1];
//容斥原理计算符合条件的数量。
if(s>=k){
rec={r,g,b};
return true;
}
}
}
}
return false;
}
inline void output(){//输出方案
printf("%d\n",ans);
reg int lr=rec.r-ans,lg=rec.g-ans,lb=rec.b-ans;
F(i,1,n){
if(a[i].r>=lr and a[i].r<=rec.r){
if(a[i].g>=lg and a[i].g<=rec.g){
if(a[i].b>=lb and a[i].b<=rec.b){
//记得-1
printf("%d %d %d\n",a[i].r-1,a[i].g-1,a[i].b-1);
--k;
if(!k)return;
}
}
}
}
}
int main() {
n=read(),k=read();
F(i,1,n)a[i].inp(),Mx=max(Mx,a[i]),Mi=min(Mi,a[i]);
init();
reg int ll=0,rr=max(Mx.b-Mi.b,max(Mx.g-Mi.g,Mx.r-Mi.r)),mid;
while(ll<=rr) {
mid=ll+rr>>1;
check(mid)?rr=mid-1,ans=mid:ll=mid+1;
}
output();
return 0;
}
inline int read() {
reg int x=0;
reg char c=getchar();
while(!isdigit(c))c=getchar();
while(isdigit(c))x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x;
}
欢迎交流讨论,请点个赞哦~
本文来自博客园,作者:Maplisky,转载请注明原文链接:https://www.cnblogs.com/lbh2021/p/14931233.html

浙公网安备 33010602011771号