2024牛客多校7-H.Database-小模拟
link:https://ac.nowcoder.com/acm/contest/81602/H
题意大概是让你模拟一个SQL语句,支持增删查,还有abort和commit操作。
对于这种模拟大概有一些经验:
- 语句的嵌套对应也写一个(解析语句的)函数的嵌套
- 长字符串的查询最好加个字符串哈希,因为这个一直TLE
- 只有简单的回退操作,直接类似可撤销并查集那样子用栈维护
#include<bits/stdc++.h>
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define endl '\n'
#define fastio ios_base::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
const int N=1005;
unordered_map<string,int> mp;
unordered_map<int,string> inv_mp;
int cnt_mp;
int get(const string &s){
if(!mp.count(s)){
mp[s]=++cnt_mp;
inv_mp[cnt_mp]=s;
}
return mp[s];
}
string inv_get(int x){return inv_mp[x];}
struct Item{
int attr[N];
};
int n,q;
#define _DEL 1
#define _INS 2
struct OP{
int type;
vector<int> ve;
};
stack<OP> stk;
struct DB{
Item items[N*3];
bool ex[N*3];
int sz;
void insert(const vector<int> & val){
sz++;
ex[sz]=true;
rep(i,1,n)items[sz].attr[i]=val[i-1];
vector<int> ve;
ve.push_back(sz);
stk.push({_INS,ve});
}
void callback(){
while(!stk.empty()){
auto [type,ve]=stk.top();
stk.pop();
if(type==_DEL){
for(auto x:ve)ex[x]=true;
}else{
for(auto x:ve)ex[x]=false;
}
}
}
vector<int> select(int dim,const int &val){
vector<int> ret;
rep(x,1,sz)if(ex[x]&&items[x].attr[dim]==val)
ret.push_back(x);
return ret;
}
vector<int> select_in(int dim,const set<int> &val){
vector<int> ret;
rep(x,1,sz)if(ex[x]&&val.count(items[x].attr[dim]))
ret.push_back(x);
return ret;
}
int del(int dim,const int &val){
int ret=0;
vector<int> ve;
rep(x,1,sz)if(ex[x])if(items[x].attr[dim]==val){
ret++;
ex[x]=false;
ve.push_back(x);
}
stk.push({_DEL,ve});
return ret;
}
int del_in(int dim,const set<int> &val){
int ret=0;
vector<int> ve;
rep(x,1,sz)if(ex[x])if(val.count(items[x].attr[dim])){
ret++;
ex[x]=false;
ve.push_back(x);
}
stk.push({_DEL,ve});
return ret;
}
}cur;
unordered_map<string,int> field_to_idx;
int find(const string &s){
int l=s.length();
rep(j,0,l-1)if(s[j]=='(')return j;
return -1;
}
vector<string> div(const string &s){
int len=s.length(),bk=0,lst=0;
vector<string> ret;
rep(i,0,len-1){
if(s[i]=='(')bk++;
else if(s[i]==')')bk--;
if(s[i]==','&&!bk){
ret.push_back(s.substr(lst,i-lst));
lst=i+1;
}
if((s[i]==')'&&bk==0)||i==len-1){
ret.push_back(s.substr(lst,i-lst+1));
lst=i+1;
}
}
return ret;
}
bool tag;
int num_del;
vector<int> solve(const string &op){
int p=find(op),len=op.length();
string type=op.substr(0,p);
auto par=div(op.substr(p+1,len-1-(p+1)));
vector<int> ret;
tag=true;
num_del=-1;
if(type=="begin"){
//
tag=false;
}else if(type=="commit"){
//
while(!stk.empty())stk.pop();
tag=false;
}else if(type=="abort"){
//
cur.callback();
tag=false;
}else{
if(type=="insert"){
vector<int> avg;
for(auto s:par)avg.push_back(get(s));
cur.insert(avg);
tag=false;
}else if(type=="select"){
auto tp=cur.select(field_to_idx[par[1]],get(par[2]));
int field=field_to_idx[par[0]];
for(auto x:tp)ret.push_back(cur.items[x].attr[field]);
tag=true;
}else if(type=="delete"){
num_del=cur.del(field_to_idx[par[0]],get(par[1]));
tag=false;
}else if(type=="select_in"){
vector<int> rec=solve(par[2]);
set<int> S;
for(auto x:rec)S.insert(x);
auto tp=cur.select_in(field_to_idx[par[1]],S);
int field=field_to_idx[par[0]];
for(auto x:tp)ret.push_back(cur.items[x].attr[field]);
tag=true;
}else if(type=="delete_in"){
vector<int> rec=solve(par[1]);
set<int> S;
for(auto x:rec)S.insert(x);
num_del=cur.del_in(field_to_idx[par[0]],S);
tag=false;
}
}
return ret;
}
int main(){
fastio;
cin>>n>>q;
rep(i,1,n){
string s;cin>>s;
field_to_idx[s]=i;
}
while(q--){
string op;
cin>>op;
auto ret=solve(op);
if(tag){
cout<<ret.size()<<endl;
int sz=ret.size();
if(sz){
cout<<inv_get(ret[1-1])<<endl;
cout<<inv_get(ret[(sz+1)/2-1])<<endl;
cout<<inv_get(ret[sz-1])<<endl;
}
}
if(num_del!=-1)cout<<num_del<<endl;
}
return 0;
}