题解:P14055 [POI 2015 R3] 路标 Direction signs
masterhuang · · 题解
设路标的位置为
那么 正确的
列我们可以找最小值减,设第
接下来要找到最大集合
首先根据
我们就可以丢弃所有存在
单独考虑第
因为
也就是说,在某个给定的
换句话说,记
直接 bitset 然后拓扑序遍历一遍,复杂度
上述结论充分性显然,必要性就是具体构造合法的
\varepsilon 。这里不赘述,感兴趣可以自己想想。
:::info[
#include<bits/stdc++.h>
#define LL long long
#define all(x) x.begin(),x.end()
#define bs basic_string<int>
#define fr(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
using namespace std;
mt19937 rnd(time(0));
const int N=1005,M=205;
int n,m,d[N][M],a[N][M],L[N],pre[N];
bitset<M>f[N];bs ans;
inline bs sol(int u)
{
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) a[i][j]=d[i][j]-d[u][j];
bs g;int w;
for(int i=1;i<=n;i++)
{
w=*min_element(a[i]+1,a[i]+1+m);
bool o=1;f[i].reset();
for(int j=1;j<=m;j++)
{
a[i][j]-=w;
if(a[i][j]>1){o=0;break;}
f[i][j]=a[i][j];
}
if(o) g+=i,L[i]=pre[i]=0;
}
sort(all(g),[](int x,int y){return f[x].count()<f[y].count();});
for(int i=0;i<g.size();i++)
{
int x=g[i];
for(int j=0;j<i;j++)
{
int y=g[j];
if((f[y]&f[x])==f[y]&&L[y]+1>L[x])
L[x]=L[y]+1,pre[x]=y;
}
}w=0;
for(int i:g) if(L[i]>=L[w]) w=i;
for(g.clear();w;w=pre[w]) g+=w;return g;
}
int main()
{
cin.tie(0)->sync_with_stdio(0);cout.tie(0);cin>>n>>m;
for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) cin>>d[i][j];
for(int i=1;i<=40;i++)
{
int x=rnd()%n+1;bs t=sol(x);
if(t.size()>ans.size()) ans=t;
}
sort(all(ans),[](int x,int y){
for(int i=1;i<=m;i++) if(d[x][i]^d[y][i]) return d[x][i]>d[y][i];
return x<y;
});cout<<ans.size()<<"\n";
for(int i:ans) cout<<i<<" ";
return 0;
}
:::