洛谷 U140761 绅士品位

洛谷 U140761 绅士品位

洛谷传送门

题目背景

虽然SeawaySeawa**y在日常服装上不拘小节,但是SeawaySeawa**y自我感觉自己是非常有生活品位的绅士。并且,他不屑与品位低的人为伍。这样,SeawaySeawa**y的周围就有了一群像SeawaySeawa**y一样绅士的朋友,SeawaySeawa**y和他们相处得很开心。但是,生活中总会有不愉快:这些朋友同样不喜欢和品位低的人为伍,并且,自负地,他们只会以自己的品位作为标准衡量他人。于是,当SeawaySeawa**y要办派对的时候,就会很头疼:他必须不能同时邀请某一个人和不屑与之为伍的其他人。

题目描述

在SeawaySeawa**y和他的朋友们眼中,有NN种行为被公认为有品位的绅士行为。但人无完人,不可能有人能同时具有这NN种行为。更特殊地,每个绅士会从这NN种行为中挑选仅55种行为,作为代表他个人品位的绅士行为。两个绅士可以为伍,当且仅当代表他们各自个人品位的55种行为中,至少有一种行为是一致的。现在,SeawaySeawa**y想知道,在他的MM个绅士朋友中,有多少对绅士是不能被同时邀请出席派对的。我们定义:两对人不同,当且仅当其中有至少一个人不同。

输入格式

从文件gentleman.ingentleman.i**n中读入数据。

第一行包括两个正整数NN和MM。NN表示绅士行为总数,这些行为从1-N1−N编号。MM表示接下来的SeawaySeawa**y的绅士朋友数量。接下来的MM行,每行五个整数。描述代表一个绅士个人品位的五种行为。

输出格式

输出到文件gentleman.outgentleman.out中。

一行一个整数,表示SeawaySeawa**y不能同时被邀请出席派对的绅士对数量。由于答案可能很大,请输出其对998244353998244353取模的结果


题解:

时空互换。

暴力可过。

稍稍优化。

代码:

#include<cstdio>
#include<bitset>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn=50000+10;
const int maxm=250000+10;
int a[maxn][5],vis[maxn],mp[maxm],tot;
ll ans;
int n,m;
bitset<maxn+10> s[10010],t[10010]; 
void solve(int l,int r,int x,int y)
{
	for(int i=x;i<=y;i++) 
		t[i-x].reset();
	for(int i=l;i<=n;i++)
		for(int j=0;j<5;j++)
			if(x<=a[i][j]&&a[i][j]<=y) 
				t[a[i][j]-x][i]=1;
	for(int i=l;i<=r;i++)
	{
		for(int j=0;j<5;j++)
			if(x<=a[i][j]&&a[i][j]<=y) 
				t[a[i][j]-x][i]=0;
		for(int j=0;j<5;j++)
			if(x<=a[i][j]&&a[i][j]<=y)
				if(!vis[i]) 
					s[i-l]=t[a[i][j]-x],vis[i]=1;
				else 
					s[i-l]|=t[a[i][j]-x];
	}
}
int main()
{
	//freopen("gentleman.in","r",stdin);
	//freopen("gentleman.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=0;j<5;j++) 
		{
			int x;
			scanf("%d",&x);
			a[i][j]=mp[++tot]=x;
		}
	sort(mp+1,mp+tot+1);
	tot=unique(mp+1,mp+tot+1)-(mp+1);
	for(int i=1;i<=n;i++)
		for(int j=0;j<5;j++) 
			a[i][j]=lower_bound(mp+1,mp+tot+1,a[i][j])-mp;
	for(int l=1,r;l<=n;l+=10000)
	{
		r=min(l+9999,n);
		for(int x=1,y;x<=tot;x+=10000)
		{
			y=min(x+9999,tot);
			solve(l,r,x,y);
		}
		for(int i=l;i<=r;i++) 
			ans+=s[i-l].count();
	}
	ans=1ll*n*(n-1ll)/2ll-ans;
	printf("%lld\n",ans);
	return 0;
}
posted @ 2020-11-17 16:28  Seaway-Fu  阅读(94)  评论(0编辑  收藏  举报