您的位置:首页 > 其它

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

2014-05-14 16:17 302 查看
传送门: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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  省选 bzoj