UVA12096 The SetStack Computer

UVA12096The 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;
}
View Code

下面这个是参考题解后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;
}
View Code
posted @ 2019-05-19 10:55  Ametsuji_akiya  阅读(136)  评论(0编辑  收藏  举报