Run ID 作者 问题 语言 测评结果 分数 时间 内存 代码长度 提交时间
35353 22级廖思学 【S】T1 C++ 解答错误 60 2000 MS 100716 KB 2399 2024-12-08 19:37:24

Tests(9/15):


#include<bits/stdc++.h> using namespace std; #define fr first #define sc second const int N=5010,C=510; int n,m,s,c[N][N],ans; bool vis[N][C][2],ap[C];//第i行/列,病毒c是否存在 struct Rge{int u,d,l,r;}a[C]; int t[C],b[C],L[C],R[C]; pair<int,int>f[C]; int tr[N]; int lowbit(int x){return x&(-x);} void add(int x,int k,int sum){ for(int i=x;i<=sum;){tr[i]+=k;i+=lowbit(i);} } int query(int x){ int ans=0; for(int i=x;i>0;){ans+=tr[i];i=i-lowbit(i);} return ans; } int Work(int i,int j){ // cout<<"!"<<i<<" "<<j<<endl; int CNT=0,ANS=0; for(int k=1;k<=m;k++)tr[k]=0; for(int k=1;k<=500;k++){ if(!ap[k])continue; if(a[k].u>=i&&a[k].d<=j){add(a[k].r,1,m);f[++CNT]={a[k].l,k};} } sort(f,f+CNT+1); for(int k=1;k<=CNT;k++){ // cout<<k<<" "; int x=s/(j-i+1); ANS=max(ANS,query(f[k].fr+x-1)); add(a[f[k].sc].r,-1,m); }//cout<<endl; return ANS; } int main(){ scanf("%d%d%d",&n,&m,&s); for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++){scanf("%d",&c[i][j]);ap[c[i][j]]=1;} } //处理出上下左右的限制 for(int i=1;i<=n;i++){ for(int j=1;j<=m;j++)vis[i][c[i][j]][0]=1; } for(int j=1;j<=m;j++){ for(int i=1;i<=n;i++)vis[j][c[i][j]][1]=1; } int ct=0; for(int k=1;k<=500;k++){ int u=5001,d=0,l=5001,r=0; for(int i=1;i<=n;i++){if(vis[i][k][0]){u=i;break;}} for(int i=n;i>=1;i--){if(vis[i][k][0]){d=i;break;}} for(int i=1;i<=m;i++){if(vis[i][k][1]){l=i;break;}} for(int i=m;i>=1;i--){if(vis[i][k][1]){r=i;break;}} a[k]={u,d,l,r}; if(u<=n){ct++;t[ct]=u;b[ct]=d;L[ct]=l;R[ct]=r;} } //算答案:固定上下两边,同时左边往右移(每次的右边可以算出),将上下两边都在限制内的矩形放 //树状数组,每次把左端点在左边之外的矩形扔掉,查询有多少个矩形的右边在算出的右边之内 sort(t+1,t+ct+1);sort(b+1,b+ct+1);sort(L+1,L+ct+1);sort(R+1,R+ct+1); // for(int i=1;i<=ct;i++)cout<<t[i]<<" "<<b[i]<<" "<<L[i]<<" "<<R[i]<<endl; for(int i=1;i<=ct;i++){ for(int j=1;j<=ct;j++){ // cout<<i<<" "<<j<<" "<<Work(i,j)<<endl; ans=max(ans,Work(t[i],b[j])); } } printf("%d\n",ct-ans); return 0; }


测评信息: