题解 [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;
}
posted @ 2022-03-26 14:18  Administrator-09  阅读(6)  评论(0编辑  收藏  举报