题意:PUSH 操作是在栈里面插入一个空集合,DUP是把栈顶的集合复制再插入栈,UNION是取出两个栈顶的集合,并求其并集再插入栈,INTERSECT是取出两个栈顶的集合,并求其交集在插入栈,ADD是取出栈顶集合,把该集合当做元素插入新的栈顶集合。
思路:ADD操作很关键也很麻烦,其他操作很简单,ADD操作需要用map,先取出栈顶集合,如果该集合没有对应的map值,赋予一个新的map值,然后把该集合的map值插入新的栈顶的集合中,由于集合的互斥性,不必担心插入的元素是否重复。如果插入新的值,那么栈顶集合的元素个数就自动+1,否则不变。
#include<cstdio>
#include<cstring>
#include<iostream>
#include<set>
#include<stack>
#include<algorithm>
#include<map>
#include<string>
using namespace std;
int cnt;
set<int>s1,s2;
stack<set<int> >stk;
map<set<int> ,int>mp;
void init()
{
cnt=1;
mp.clear();
while(!stk.empty())
stk.pop();
}
void Push()
{
set<int>s;
stk.push(s);
printf("0\n");
}
void Dup()
{
set<int>s;
s=stk.top();
stk.push(s);
printf("%d\n",s.size());
}
void Union()
{
s1=stk.top();stk.pop();
s2=stk.top();stk.pop();
set<int>::iterator it;
for(it=s1.begin();it!=s1.end();it++)
s2.insert(*it);
stk.push(s2);
printf("%d\n",s2.size());
}
void Intersect()
{
s1=stk.top();stk.pop();
s2=stk.top();stk.pop();
set<int>s;
set<int>::iterator it;
for(it=s1.begin();it!=s1.end();it++)
if(s2.find(*it)!=s2.end())
s.insert(*it);
stk.push(s);
printf("%d\n",s.size());
}
void Add()
{
s1=stk.top();stk.pop();
s2=stk.top();stk.pop();
if(!mp[s1])
mp[s1]=++cnt;
s2.insert(mp[s1]);
stk.push(s2);
printf("%d\n",s2.size());
}
int main()
{
int T;
scanf("%d",&T);
string s;
while(T--)
{
int q;
char op[20];
scanf("%d",&q);
init();
while(q--)
{
scanf("%s",op);
if(op[0]=='P')
Push();
else if(op[0]=='D')
Dup();
else if(op[0]=='U')
Union();
else if(op[0]=='I')
Intersect();
else
Add();
}
printf("***\n");
}
}