UVA12096 The SetStack Computer
需要对每个集合用一个ID来代替,方便在栈中模拟,毕竟操作最多10000个,意味着ID最多只有10000个。
然后要做set和ID(int型)之间的双映射,也就是操作时从栈中取出ID,开一个vector<set<int> >,下标对应集合ID,每一个都是一个集合,里面有他包含的集合元素的ID;入栈时需要把操作得到的集合找出其ID,若没有则开一个新的。
所以就是map<set<int>,int>实现。(开拓眼界了。。)
查找的复杂度$O(玄学)$
还有就是才知道有这样几个函数可以帮助实现集合的并集、交集,比我手写的快多了,还很方便。除了可以用在set上,好像vector也可以。。
set_union(a.begin(),a.end(),b.begin(),b.end(),inserter(c,c.begin()));(并集)
set_intersection(a.begin(),a.end(),b.begin(),b.end(),inserter(c,c.begin()));(交集)
这表示有a从begin(迭代器)到end这段的集合和b的begin到end的这段的集合,将上述两者取并集or交集后塞到c的begin开始之后(inserter是什么?我也不知道就依葫芦画瓢用吧。。)。
先放一开始写的代码,不知道上面那些玩意儿,思路比较狭窄,uva是RE了,uvalive和hdu上可以水过。
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<set> #include<map> #define dbg(x) cerr<<#x<<" = "<<x<<endl #define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl using namespace std; typedef long long ll; template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} template<typename T>inline T _min(T A,T B){return A<B?A:B;} template<typename T>inline T _max(T A,T B){return A>B?A:B;} template<typename T>inline T read(T&x){ x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; } const int N=2000+7; set<int> s[N]; map<set<int>,int> mp; int T,m,tot,Top; char ch[14]; struct thxORZ{ int a[N],Top; inline void clear(){Top=0;} inline void push(){a[++Top]=1;} inline void copy(){++Top,a[Top]=a[Top-1];} inline void add(){ --Top;if(s[a[Top]].find(a[Top+1])==s[a[Top]].end()){ set<int> tmp=s[a[Top]];tmp.insert(a[Top+1]); map<set<int>,int>::iterator it=mp.find(tmp); if(it!=mp.end())a[Top]=it->second; else a[Top]=++tot,mp[tmp]=tot,s[tot]=tmp; } } inline void Union(){ --Top;set<int> tmp=s[a[Top]]; for(register set<int>::iterator it=s[a[Top+1]].begin();it!=s[a[Top+1]].end();++it)tmp.insert(*it); map<set<int>,int>::iterator it=mp.find(tmp); if(it!=mp.end())a[Top]=it->second; else a[Top]=++tot,mp[tmp]=tot,s[tot]=tmp; } inline void intersect(){ --Top;set<int> tmp;tmp.clear(); for(register set<int>::iterator it=s[a[Top]].begin();it!=s[a[Top]].end();++it) if(s[a[Top+1]].find(*it)!=s[a[Top+1]].end())tmp.insert(*it); map<set<int>,int>::iterator it=mp.find(tmp); if(it!=mp.end())a[Top]=it->second; else a[Top]=++tot,mp[tmp]=tot,s[tot]=tmp; } inline int print(){printf("%d\n",s[a[Top]].size());} }thx; int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout); read(T);while(T--){ mp.clear();for(register int i=2;i<=tot;++i)s[i].clear(); mp[s[1]]=tot=1;thx.clear(); read(m);while(m--){ scanf("%s",ch); switch(ch[0]){ case 'P':thx.push(),thx.print();break; case 'D':thx.copy(),thx.print();break; case 'A':thx.add(),thx.print();break; case 'U':thx.Union(),thx.print();break; case 'I':thx.intersect(),thx.print();break; } } puts("***"); } return 0; }
下面这个是参考题解后improve过的,uva上就不会出错了,但是poj1000ms时限卡STL。。死活过不去,必须要写集合的hash使得log查找变成线性的。。我不会,算了算了逃了
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<vector> #include<map> #include<set> #define dbg(x) cerr<<#x<<" = "<<x<<endl #define _dbg(x,y) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<endl using namespace std; typedef long long ll; typedef set<int> thx; template<typename T>inline char MIN(T&A,T B){return A>B?A=B,1:0;} template<typename T>inline char MAX(T&A,T B){return A<B?A=B,1:0;} template<typename T>inline T _min(T A,T B){return A<B?A:B;} template<typename T>inline T _max(T A,T B){return A>B?A:B;} template<typename T>inline T read(T&x){ x=0;int f=0;char c;while(!isdigit(c=getchar()))if(c=='-')f=1; while(isdigit(c))x=x*10+(c&15),c=getchar();return f?x=-x:x; } const int N=10000+7; vector<thx> s; map<thx,int> mp; int sta[N],t; int T,n; char opt[15]; inline int get_ID(thx S){ if(mp.find(S)!=mp.end())return mp[S]; s.push_back(S); return mp[S]=s.size()-1; } inline void PUSH(){sta[++t]=0;} inline void DUP(){++t,sta[t]=sta[t-1];} inline void UNION(){ thx tmp,s1=s[sta[t]],s2=s[sta[--t]]; set_union(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(tmp,tmp.begin())); sta[t]=get_ID(tmp); } inline void INTERSECT(){ thx tmp,s1=s[sta[t]],s2=s[sta[--t]]; set_intersection(s1.begin(),s1.end(),s2.begin(),s2.end(),inserter(tmp,tmp.begin())); sta[t]=get_ID(tmp); } inline void ADD(){ thx tmp=s[sta[--t]]; tmp.insert(sta[t+1]); sta[t]=get_ID(tmp); } int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout); thx orz;orz.clear();s.push_back(orz);mp[orz]=0; read(T);while(T--){ t=0; read(n);while(n--){ scanf("%s",opt); switch(opt[0]){ case 'P':PUSH();break; case 'D':DUP();break; case 'U':UNION();break; case 'I':INTERSECT();break; case 'A':ADD();break; } printf("%d\n",s[sta[t]].size()); } puts("***"); } return 0; }