两周没出题了,这两周过得很颓废,不想看书不想做题不想听课,一直玩游戏啊玩游戏。突然一天清晨醒来发现自己在这样下去就完了,于是开始有意识的自己上自习,以前可没有上自习这种想法- -,这几天天冷了,不想动弹- -,可是我在努力的克服!(又逗比了)不扯了切入正题。

当初看这道题的时候是在想不明白为什么要有ID这个奇葩的玩意儿,百度也百度不到,昨天又看了一遍居然懂了,这果然是个好东西。

typedef struct set<int> Set;

定义了一个set的结构体,用来保存集合。


map<Set, int> IDcache;

每一种集合({}, {{},{{}}}等)对应一个数字ID,这个ID主要是记录这种集合有没有出现过。


int ID(Set x) {
    if(IDcache.count(x)) return IDcache[x];
    Setcache.push_back(x);
    return IDcache[x] = Setcache.size() - 1;
}

这ID就相当于身份证号码,如果身份证已经注册了,就返回身份证号码,如果没有就注册个身份证,并返回新注册的身份证号码。

身份证号码主要为了调用集合。

vector<Set> Setcache;


#include<iostream>
#include<set>
#include<stack>
#include<map>
#include<vector>
#include<algorithm>
#define ALL(x) x.begin(), x.end()
#define INF(x) inserter(x, x.begin())
using namespace std;

typedef struct set<int> Set;
map<Set, int> IDcache;
vector<Set> Setcache;

int ID(Set x) {
    if(IDcache.count(x)) return IDcache[x];
    Setcache.push_back(x);
    return IDcache[x] = Setcache.size() - 1;
}

int main() {
    int T, N;
    cin >> T;
    while(T--) {
        stack<int> s;
        cin >> N;
        while(N--) {
            char cmd[10];
            cin >> cmd;
            if(cmd[0] == 'P') s.push(ID(Set()));
            else if(cmd[0] == 'D') s.push(s.top());
            else {
                Set x, x1, x2;
                x1 = Setcache[s.top()]; s.pop();
                x2 = Setcache[s.top()]; s.pop();
                if(cmd[0] == 'U') set_union (ALL(x1), ALL(x2), INF(x));
                if(cmd[0] == 'I') set_intersection (ALL(x1), ALL(x2), INF(x));
                if(cmd[0] == 'A') {x = x2; x.insert(ID(x1));}
                s.push(ID(x));
            }
            cout << Setcache[s.top()].size() << endl;
        }
        cout << "***" << endl;
    }
}