2024牛客多校7-H.Database-小模擬

yoshinow2001發表於2024-08-07

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;
}