[湖南集训] Hungry Rabbit [Hard-]
前言
简述题意
比较形式化。
有 \(n\) 只兔子,有 \(m\) 天,第 \(i\) 天有一个集合 \(S_i\),第一天需要构造一个大小为 \(k\) 的兔子集合,然后之后每天你可以之多改变兔子集合内至多 \(l\) 个元素(当然需要满足改变后兔子集合大小仍为 \(k\))。我们需要满足第 \(i\) 天的兔子集合与 \(S_i\) 没有交集,要求构造合法方案。
解题思路
挺好的贪心题目呢。
因为每天换的兔子个数对于下一天是没有任何影响的,所以如果能多换兔子更优那么尽量多换兔子。
现在考虑怎样换兔子最优,显然是把最不优的兔子换成不在兔子集合内最优的兔子,进行 \(l\) 次(当然如果兔子集合已经最优就不用用满 \(l\) 次)。
于是我们考虑怎样定义兔子“优秀”,发现对比兔子集合内一个兔子,这个兔子被吃掉的天数如果更晚,那么换成这只兔子一定不劣,因为这可以让你之后换兔子的操作变少一点,意味着有更多机会换成更优的兔子。
接下来就是套数据结构模拟该过程了。
我们用两个堆维护当前兔子集合,和“候选”兔子集合,则每次我们可以将当前兔子集合中最不优的和候选兔子集合中最优的进行比较、交换,这样至多只会进行 \(l\) 次操作。然后判断当前兔子集合是否满足所有兔子在当天都不会被吃掉即可。
时间复杂度:因为 \(n,m,l,k\) 都同阶,所以直接用 \(n\) 表示,\(O(n^2 \log n)\),对于 \(n \leq 800\) 赢麻了。
Code
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define uint unsigned int
#define ld long double
#define fir first
#define sec second
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ls(x) (x<<1)
#define rs(x) (x<<1|1)
#define lowbit(x) (x&-x)
using namespace std;
namespace FastIO{ //这是省缺源
const int Size=1<<21;
char ibuf[Size],obuf[Size],*p1=ibuf,*p2=ibuf,*p3=obuf;
#define getchar() (p1==p2&&(p2=(p1=ibuf)+fread(ibuf,1,Size,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<Size?(*p3++=(x)):(fwrite(obuf,1,p3-obuf,stdout),p3=obuf,*p3++=(x)))
inline void flush(){if(p3>obuf) fwrite(obuf,1,p3-obuf,stdout),p3=obuf;}
template<class T>
T read(T&x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)) f|=!(ch^'-'),ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch&0xF),ch=getchar();
x=(f?-x:x);return x;
}template<class T>
int reads(T*s){
char ch=getchar();int len=0;
while(ch==' '||ch=='\n'||ch=='\r') ch=getchar();
while(ch!=' '&&ch!='\n'&&ch!=EOF&&ch!='\r') s[len++]=ch,ch=getchar();
s[len]='\0';return len;
}template<class T>
T readd(T&x){
x=0;bool f=false;char ch=getchar();
while(!isdigit(ch)) f|=!(ch^'-'),ch=getchar();
while(isdigit(ch)) x=x*10+(ch&0xF),ch=getchar();
if(ch=='.'){ch=getchar();T d=1;while(isdigit(ch)) d*=0.1,x+=d*(ch&0xF),ch=getchar();}
x=(f?-x:x);return x;
}template<class T>
void write(T x,char ch=' '){
if(x<0) putchar('-'),x=-x;
char tmp[41];int cnt=0;
while(x>9) tmp[cnt++]=x%10+'0',x/=10;tmp[cnt++]=x+'0';
while(cnt) putchar(tmp[--cnt]);putchar(ch);
}template<class T>
void writes(T x,int l=0,int r=-1){
if(~r){for(int i=l;i<=r;i++) putchar(x[i]);}
else{for(int i=l;x[i];i++) putchar(x[i]);}
}template<class T>
void writed(T x,int p=6,char ch=' '){
if(x<0) putchar('-'),x=-x;
T d=0.5;for(int i=0;i<p;i++) d*=0.1;x+=d;
ll g=(ll)(x);p?write(g,'.'):write(g,ch);
if(p){T f=x-g;for(int i=0,d;i<p;i++) f*=10,d=(int)(f),putchar(d+'0'),f-=d;putchar(ch);}
}
}
using namespace FastIO;
const int N=8e2+10;
struct node{
int u,nxt;
inline bool operator>(const node&o) const{return nxt>o.nxt;}
inline bool operator<(const node&o) const{return nxt<o.nxt;}
};
int nxt[N][N],ans[N][N],n,m,k,l;
priority_queue<node,vector<node>,greater<node> >q;
priority_queue<node>now;
char str[N][N],s[N][N];
bool vis[N];
int main(){
read(m),read(n),read(k),read(l);
for(int i=1;i<=m;i++) reads(str[i]+1);
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++) s[i][j]=str[j][i];
}
for(int i=1;i<=m;i++) nxt[n+1][i]=n+1;
for(int i=n;i>=1;i--){
for(int j=1;j<=m;j++){
if(s[i][j]=='1') nxt[i][j]=nxt[i+1][j];
else nxt[i][j]=i;
}
}
for(int i=1;i<=m;i++){
q.push({i,nxt[1][i]});
vis[i]=true;
}
while(q.size()>k) vis[q.top().u]=false,q.pop();
if(q.top().nxt==1){writes("-1\n"),flush();return 0;}
int cnt=0;
for(int i=1;i<=m;i++){
if(vis[i]) ans[1][++cnt]=i;
}
for(int i=2;i<=n;i++){
while(!now.empty()) now.pop();
for(int j=1;j<=m;j++){
if(!vis[j]) now.push({j,nxt[i][j]});
}
int cnt=0;
while(q.top().nxt<now.top().nxt){
node tmp1=q.top(),tmp2=now.top();
q.pop(),now.pop();
q.push(tmp2),now.push(tmp1);
vis[tmp1.u]=false,vis[tmp2.u]=true;
cnt++;
if(cnt==l) break;
}
cnt=0;
if(q.top().nxt==i){writes("-1\n"),flush();return 0;}
for(int j=1;j<=m;j++){
if(vis[j]) ans[i][++cnt]=j;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=k;j++) write(ans[i][j]);
putchar('\n');
}
flush();
return 0;
}

浙公网安备 33010602011771号