题解 [NOI Online 2022 提高组] 讨论
把 !isinc
打成 isinc
没有看出来(或者忙于代码没交上没有看?)挂了十分
只要是检查了应该都能查出来吧……
但是交上去的代码就是错成了这样个鬼样子
正解:
其实能想出来开桶再排序的暴力应该能意识到……
考虑按会做的题数从大到小加入一个人
对每道题维护一个 \(t_i\) 为一个会做它的人
加入一个人时考虑若他会做的题的 \(t\) 不全相等则他一定讨论
从这些 \(t_i\) 中挑出 \(siz\) 最小的与他讨论输出即可
否则将他会做的题的 \(t_i\) 都覆盖成他自己
MD 省选考成这个垃圾样子我就真退役了
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 1000010
#define fir first
#define sec second
#define pb push_back
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n;
int siz[N];
vector<int> a[N];
namespace force{
bitset<1010> s[1010], t;
void solve() {
for (int i=1; i<=n; ++i) s[i].reset();
for (int i=1; i<=n; ++i) for (auto it:a[i]) s[i][it]=1;
for (int i=1; i<=n; ++i) {
for (int j=i+1; j<=n; ++j) {
t=s[i]&s[j];
if (t.any() && t!=s[i] && t!=s[j]) {
puts("YES");
cout<<i<<' '<<j<<endl;
return ;
}
}
}
puts("NO");
}
}
namespace task1{
bool vis[5002][5002];
vector<int> buc[N];
bitset<5002> s[5002];
// pair<int, int>
void solve() {
// cout<<double(sizeof(vis)+sizeof(s)+sizeof(buc))/1000/1000<<endl;
memset(vis, 0, sizeof(vis));
for (int i=1; i<=n; ++i) buc[i].clear();
for (int i=1; i<=n; ++i) s[i].reset();
for (int i=1; i<=n; ++i) for (auto it:a[i]) s[i][it]=1;
for (int i=1; i<=n; ++i) for (auto it:a[i]) buc[it].pb(i);
for (int i=1; i<=n; ++i) sort(buc[i].begin(), buc[i].end(), [](int a, int b){return siz[a]<siz[b];});
for (int i=1; i<=n; ++i) {
for (int j=1; j<buc[i].size(); ++j) if (!vis[buc[i][j-1]][buc[i][j]]) {
if ((s[buc[i][j-1]]&s[buc[i][j]])!=s[buc[i][j-1]]) {
puts("YES");
cout<<buc[i][j-1]<<' '<<buc[i][j]<<endl;
return ;
}
vis[buc[i][j-1]][buc[i][j]]=1;
}
}
puts("NO");
}
}
namespace task2{
bool vis[N];
vector<int> buc[N];
int cnt[20], tem[N];
bool isinc(int i, int j) {
for (auto& it:a[j]) vis[it]=1;
for (auto& it:a[i]) if (!vis[it]) {
for (auto& it:a[j]) vis[it]=0;
return 0;
}
for (auto& it:a[j]) vis[it]=0;
return 1;
}
void solve() {
// cout<<double(sizeof(vis)+sizeof(s)+sizeof(buc))/1000/1000<<endl;
memset(vis, 0, sizeof(vis));
for (int i=1; i<=n; ++i) buc[i].clear();
for (int i=1; i<=n; ++i) for (auto& it:a[i]) buc[it].pb(i);
for (int i=1; i<=n; ++i) {
if (buc[i].size()<30) sort(buc[i].begin(), buc[i].end(), [](int a, int b){return siz[a]<siz[b];});
else {
// vector<int> bkp=buc[i];
memset(cnt, 0, sizeof(cnt));
for (auto& it:buc[i]) ++cnt[siz[it]];
for (int i=1; i<=10; ++i) cnt[i]+=cnt[i-1];
for (auto& it:buc[i]) tem[cnt[siz[it]]--]=it;
for (int j=0; j<buc[i].size(); ++j) buc[i][j]=tem[j+1];
// for (int j=0; j+1<buc[i].size(); ++j) assert(siz[buc[i][j]]>=siz[buc[i][j+1]]);
// sort(buc[i].begin(), buc[i].end(), [](int a, int b){return siz[a]==siz[b]?a<b:siz[a]<siz[b];});
// sort(bkp.begin(), bkp.end(), [](int a, int b){return siz[a]==siz[b]?a<b:siz[a]<siz[b];});
// assert(buc[i]==bkp);
}
}
// for (int i=1; i<=n; ++i) sort(buc[i].begin(), buc[i].end(), [](int a, int b){return siz[a]<siz[b];});
for (int i=1; i<=n; ++i) {
for (int j=1; j<buc[i].size(); ++j) {
if (!isinc(buc[i][j-1], buc[i][j])) {
puts("YES");
cout<<buc[i][j-1]<<' '<<buc[i][j]<<endl;
return ;
}
}
}
puts("NO");
}
}
namespace task{
int t[N], pos[N];
void solve() {
for (int i=1; i<=n; ++i) pos[i]=i, t[i]=0;
sort(pos+1, pos+n+1, [](int a, int b){return siz[a]>siz[b];});
for (int i=1; i<=n; ++i) {
int lst=-1; bool flag=0;
for (auto it:a[pos[i]])
if (lst==-1) lst=t[it];
else if (lst!=t[it]) flag=1;
if (flag) {
int minn=INF, mini;
for (auto it:a[pos[i]])
if (t[it]&&siz[t[it]]<minn) minn=siz[t[it]], mini=t[it];
puts("YES");
cout<<pos[i]<<' '<<mini<<endl;
return ;
}
else {for (auto it:a[pos[i]]) t[it]=pos[i];}
}
puts("NO");
}
}
signed main()
{
// freopen("discuss.in", "r", stdin);
// freopen("discuss.out", "w", stdout);
int T=read();
while (T--) {
n=read();
for (int i=1; i<=n; ++i) a[i].clear();
for (int i=1,k; i<=n; ++i) {
k=read(); siz[i]=k;
while (k--) a[i].pb(read());
}
// if (n<=300) force::solve();
// else if (n<=5000) task1::solve();
// else task2::solve();
task::solve();
}
return 0;
}