HZOJ 集合论

考场用的set,代码复杂度很低,时间复杂度$O(sum log)$,一发过了大样例,觉得1e6的数据很稳了就没再管(而后就挂掉了……)ios

考后把set化成unordered_set就A了。其实$sum log$的时间复杂度是没有什么问题,只不过有个细节没有考虑好,考场上觉得set赋值和clear的复杂度是O1的,而后就挂掉了。spa

其实用unordered_set复杂度也不是很对,瓶颈在于赋值和清空。blog


题解:

考虑用set s维护,顺便用一个变量sum维护set中数据的和。get

对于操做1;考虑B集合中的变量a,在s中find(a),若不存在,插入,sum+=a;string

对于操做2:sum=0。考虑B集合中的变量a,在s中find(a),若存在,在另一个set s1插入a,sum+=a。s=s1,s1.clear()。本人死于此。it

对于操做3,4:对于s中每一个数都进行操做显然不可行,那么考虑用一个变量cal维护总体变化值,只须要给操做1,2的a减cal再进行操做便可。io

以后考虑怎么不用set实现:class

咱们并不要求数据有序,显然能够用unordered_set,可是其实能够用常数更小的Hash_map实现。stream

以后考虑以前的赋值和清空操做:记录一个时间戳便可。变量

#include<iostream>
#include<cstring>
#include<cstdio>
#include<unordered_set>
#define LL long long
using namespace std;
char xch,xB[1<<15],*xS=xB,*xTT=xB;
#define getc() (xS==xTT&&(xTT=(xS=xB)+fread(xB,1,1<<15,stdin),xS==xTT)?0:*xS++)
int m;

LL cal=0,sum;
unordered_set<int>s,s1;
#define IT set<int>::iterator
inline int read();
signed main()
{
//	freopen("ex_jihe4.in","r",stdin);
//	freopen("11.out","w",stdout);
	
	m=read();int opt;
	for(int i=1;i<=m;i++)	
	{
		opt=read();
		if(opt==1)
		{
			int siz=read(),a;
			for(int j=1;j<=siz;j++)
			{	
				a=read();a-=cal;
				if(s.find(a)==s.end())s.insert(a),sum+=a;
			}
		}
		if(opt==2)
		{
			int siz=read(),a;sum=0;
			for(int j=1;j<=siz;j++)	
			{
				a=read();a-=cal;
				if(s.find(a)!=s.end())s1.insert(a),sum+=a;
			}
			s=s1;s1.clear();
		}
		if(opt==3)
		{
			if(!s.empty())cal++;
		}
		if(opt==4)
		{
			if(!s.empty())cal--;
		}
		printf("%lld\n",sum+cal*s.size());
	}
}
inline int read()
{
	int x=0,f=1;char ch=getc();
	while(ch<'0'|ch>'9'){if(ch=='-')f=-1;ch=getc();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getc();}
	return x*f;
}
相关文章
相关标签/搜索