传送门: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; }