【BZOJ】【P3578】【GTY的人类基因组计划2】【题解】【线段树套set or 线段树+set+hash】

传送门:www.lydsy.com/JudgeOnline/problem.php?id=3578

做为出题人当然要写题解啦……

数据结构题大水题……,题意不用我说了吧……注意1,2,3做了实验,1,2做还会产生2点点数,1,2,3,4做还会产生4点点数

判重是重点,蒟蒻已经在下方注明了:善用STL……,于是map<set<int>,bool> 即可……呃……

于是线段树维护区间,套平衡树,显然只有叶节点才需要用平衡树,区间做实验既是查询又是修改,需要打标记,然后传标记就好了……呃,真是大水题一个

数据全为随机生成,只有两个极限数据……不过暴力当然是不能过的了……haha

第一次在bzoj上出题,如果数据错了请联系我,我会认真改正

数据+标程:pan.baidu.com/s/1hqj3ZYO

===========================================

刚上bzoj 5min就被发现数据弱了……呃……在n=100000,m=2,q=100000的数据后标程T成翔,一看内存都吃了一个G了!!!,看来蒟蒻还是得好好想想了……

===========================================

作为出题人蒟蒻没想到会有这么多种做法,无限YM各位神犇,再列出两种做法:

1.


hash集合原来可以这样……OTZ

2.(这是目前Rank1 wwx神犇的做法):


目前还没读懂,200+ms跪烂

===========================================

PS:hash选种子真TM蛋疼,过不了的可以尝试改改srand()的种子,或者……对着数据改……


Code:

/*
	ID:zky
*/
#include<map>
#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L i<<1
#define R i<<1|1
using namespace std;
const int maxn=1e5+10;
const int maxm=1e5+10;
const int maxq=1e5+10;
int n,m,q;
map<set<int>,int>M;
int home[maxn];
struct seg_tree{
	struct node{
		set<int>s;
		int size,lazy;
		node(){
			size=lazy=0;
		}
	};
	node t[maxn<<2];
	void deb(int i){
//		printf("#%d size:%d lazy:%d\n",i,t[i].size,t[i].lazy);
//		for(set<int>::iterator it=t[i].s.begin();it!=t[i].s.end();it++)
//			cout<<*it<<" ";
//		cout<<endl;
	}
	void pushdown(int i,int l,int r){
		if(t[i].lazy==0)return;
		int mid=l+r>>1;
		if(l==mid)
			M[t[L].s]=1;
		if(r==mid+1)
			M[t[R].s]=1;
		t[L].lazy=1;
		t[L].size=0;
		t[R].lazy=1;
		t[R].size=0;
		t[i].lazy=0;
	}
	void rz(int i){
		t[i].size=0;
//		if(!M.count(t[L].s))
		t[i].size+=t[L].size;
//		1if(!M.count(t[R].s))		
		t[i].size+=t[R].size;
	}
	void Change(int i,int l,int r,int pos,int val){
		deb(i);
		if(l==r){
			deb(i);
			t[i].s.insert(val);
			if(!M.count(t[i].s))
				t[i].size=t[i].s.size();
			else
				t[i].size=0;
			deb(i);
			return ;
		}
		int mid=l+r>>1;
		pushdown(i,l,r);
		if(pos<=mid)Change(lson,pos,val);
		else Change(rson,pos,val);
		rz(i);
		deb(i);
	}
	void Erase(int i,int l,int r,int pos,int val){
		deb(i);
		if(l==r){
			deb(i);
			t[i].s.erase(val);
			if(!M.count(t[i].s))
				t[i].size=t[i].s.size();
			else
				t[i].size=0;
			deb(i);
			return ;
		}
		int mid=l+r>>1;
		pushdown(i,l,r);
		if(pos<=mid)Erase(lson,pos,val);
		else Erase(rson,pos,val);
		rz(i);
		deb(i);
	}
	int qsum(int i,int l,int r,int l0,int r0){
		deb(i);
		if(l0<=l&&r0>=r){
			deb(i);
			M[t[i].s]=1;
			int s=t[i].size;
			t[i].size=0;
			t[i].lazy=1;
			deb(i);
			return s;
		}
		pushdown(i,l,r);
		int mid=l+r>>1;

		int ans=0;
		if(l0<=mid)ans+=qsum(lson,l0,r0);
		if(r0>mid) ans+=qsum(rson,l0,r0);
		rz(i);
		deb(i);
		return ans;
	}
}T;
void Change(int i,int j){
	if(home[i])
	T.Erase(1,1,n,home[i],i);
	T.Change(1,1,n,(home[i]=j),i);
}
int Qsum(int l,int r){
	return T.qsum(1,1,n,l,r);
}
int getint(){
	int res=0,ok=0;char ch;
	while(1){
		ch=getchar();
		if(ch<='9'&&ch>='0'){
			res*=10;res+=ch-'0';ok=1;
		}else if(ok)break;
	}return res;
}
int main(){
	n=getint();m=getint();q=getint();
	for(int i=1;i<=n;i++)Change(i,1);
	while(q--){
		char opt[3];scanf("%s",opt);
		if(opt[0]=='C'){
			int i=getint(),j=getint();
			Change(i,j);
		}else{
			int l=getint(),r=getint();
			printf("%d\n",Qsum(l,r));
		}
//		for(map<set<int>,int>::iterator it=M.begin();it!=M.end();it++)
//			for(set<int>::iterator i=it->first.begin();i!=it->first.end();i++)
//				cout<<*i<<" ";
//		cout<<endl;
	}
	return 0;
}


hash:

/*
	ID:zky
*/
#include<set>
#include<cctype>
#include<cstdlib>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define lson i<<1,l,mid
#define rson i<<1|1,mid+1,r
#define L i<<1
#define R i<<1|1
using namespace std;
const int maxn=1e5+10;
typedef unsigned long long lld;
lld MOD=100000000000007LL;
set<lld>hash;
lld mp[maxn];
int room[maxn];
int n,m,q;
lld t[maxn<<2];
int size[maxn<<2];
int rsize[maxn<<2];
int lazy[maxn<<2];
struct seg_tree{

	seg_tree(){
		memset(t,0,sizeof(t));
		memset(size,0,sizeof(size));
		memset(lazy,0,sizeof(lazy));
		memset(rsize,0,sizeof(rsize));
	}
	void pushdown(int i,int l,int r){
		if(!lazy[i])return;
		int mid=l+r>>1;
		if(l==mid)
			hash.insert(t[L]);
		if(r==mid+1)
			hash.insert(t[R]);
		size[L]=0;
		size[R]=0;
		lazy[L]=1;
		lazy[R]=1;		
		lazy[i]=0;
	}
	void rz(int i){
		size[i]=size[L]+size[R];
	}
	void Erase(int i,int l,int r,int pos,int val){
		if(l==r){
			t[i]^=mp[val];
			rsize[i]--;
			if(!hash.count(t[i]))
				size[i]=rsize[i];
			else
				size[i]=0;
			return;
		}
		pushdown(i,l,r);
		int mid=l+r>>1;
		if(pos<=mid)Erase(lson,pos,val);
		else Erase(rson,pos,val);
		rz(i);
	}
	void Change(int i,int l,int r,int pos,int val){
		if(l==r){
			t[i]^=mp[val];
			rsize[i]++;
			if(!hash.count(t[i]))
				size[i]=rsize[i];
			else
				size[i]=0;
			return;
		}
		pushdown(i,l,r);
		int mid=l+r>>1;
		if(pos<=mid)Change(lson,pos,val);
		else Change(rson,pos,val);
		rz(i);
	}
	int qsum(int i,int l,int r,int l0,int r0){
		if(l0<=l&&r0>=r){
			hash.insert(t[i]);
			int s=size[i];
			size[i]=0;
			lazy[i]=1;
			return s;			
		}
		pushdown(i,l,r);
		int mid=l+r>>1;
		int ans=0;
		if(l0<=mid)ans+=qsum(lson,l0,r0);
		if(r0>mid) ans+=qsum(rson,l0,r0);
		rz(i);
		return ans;		
	}
}T;
void Change(int i,int j){
	if(room[i])
	T.Erase(1,1,n,room[i],i);
	T.Change(1,1,n,(room[i]=j),i);
}
int Qsum(int l,int r){
	return T.qsum(1,1,n,l,r);
}
int getint(){
	int res=0,ok=0;char ch;
	while(1){
		ch=getchar();
		if(ch<='9'&&ch>='0'){
			res*=10;res+=ch-'0';ok=1;
		}else if(ok)break;
	}return res;
}
int main(){
	srand(112);
//	freopen("input10.txt","r",stdin);
	n=getint();m=getint();q=getint();
	for(int i=1;i<=n;i++)mp[i]=(rand()*13131+21313*(rand()+756753))*10007;
	for(int i=1;i<=n;i++)Change(i,1);
	while(q--){
		char opt[3];scanf("%s",opt);
		if(opt[0]=='C'){
			int i=getint(),j=getint();
			Change(i,j);
		}else{
			int l=getint(),r=getint();
			printf("%d\n",Qsum(l,r));
		}
	}
	return 0;
}

3.Orz wwx

/*
	ID:zky
*/
#include<set>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=1e5+10;
typedef unsigned long long lld;
set<lld>hash;
set<int>s;
lld mp[maxn];
lld room[maxn];
int size[maxn];
int bel[maxn];
int n,m,q;
int getint(){
	int res=0,ok=0;char ch;
	while(1){
		ch=getchar();
		if(ch<='9'&&ch>='0'){
			res*=10;res+=ch-'0';ok=1;
		}else if(ok)break;
	}return res;
}
void Change(int i,int j){
	room[bel[i]]^=mp[i];
	size[bel[i]]--;
	if(!hash.count(room[bel[i]]))
		s.insert(bel[i]);
	else
		s.erase(bel[i]);
	room[(bel[i]=j)]^=mp[i];
	size[bel[i]]++;
	if(!hash.count(room[bel[i]]))
		s.insert(bel[i]);
	else
		s.erase(bel[i]);	
}
int Qsum(int l,int r){
	int ans=0;
	
	for(;;){
		set<int>::iterator it=s.lower_bound(l);
		if(it==s.end()||*it>r)break;
		int deb=*it;
		ans+=size[*it];
		hash.insert(room[*it]);
		s.erase(it);
	}
	
	return ans;
}
int main(){
	srand(112);
	n=getint();m=getint();q=getint();
	for(int i=1;i<=n;i++)mp[i]=(rand()*13131+21313*(rand()+756753))*10007;
	size[1]=n;
	for(int i=1;i<=n;i++){
		room[1]^=mp[i];
		bel[i]=1;
	}
	s.insert(1);
	while(q--){
		char opt[3];scanf("%s",opt);
		if(opt[0]=='C'){
			int i=getint(),j=getint();
			Change(i,j);
		}else{
			int l=getint(),r=getint();
			printf("%d\n",Qsum(l,r));
		}
	}		
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值