2023 CSP-J/S 复赛(简要思路)

省流:都没 AK,但是思路都没假。(没更新,小声)

upd:J \(400\),S \(385\)

J

apple

\(O(\log n)\) 模拟,因为 \(n\) 每次乘 \(\frac{2}{3}\)\(x≡1\mod 3\) 时第 \(x\) 个苹果会被拿走。

road

贪心。每次选价格最少的油加。

uqe

按照题意模拟。\(c=0\) 也许要特判。

bus

我的方法是二分答案然后倒着最短路,\(mn_{i,j}\) 为到了 \(i\) 这个点时间 \(\mod k\)\(j\) 的最短时间。

我的再小图灵上 TLE \(60\),但听说有人过了。

S

lock

可以直接枚举,其实也有一个 \(O(N)\) 的算法。

game

CF 原题。设 \(dp_{i}\) 为结尾为第 \(i\) 个的可以消掉的序列个数。考虑如果有两个相邻的相同的字母,可以把他们消掉。记录一个 map,代表上一个有用的【一个字母】在【那个地方】。两个相邻的相同的字母消掉以后,他们给答案贡献一个 \(1\)(对于一个位置),然后就没用了,可以直接缩掉。

因为我说的很烂,所以相对而讲,代码也许更好懂。

赛时代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 2e6+6;

ll n,dp[N];
char s[N];
unordered_map<char,int> mp[N];

int main(){
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    scanf("%lld %s",&n,s+1);
    ll ans=0;
    for (int i=1; i<=n; i++){
        if (mp[i-1].count(s[i])){
            int t=mp[i-1][s[i]];
            dp[i]+=dp[t-1]+1;
            swap(mp[t-1],mp[i]);
        }
        mp[i][s[i]]=i;
        ans+=dp[i];
       // cout<<dp[i]<<" ";
    }
    printf("%lld\n",ans);
    return 0;
}

/*
 - int/long long?
 - memory?
 - init for multiple cases?
 - modular?
 - read the problem statement.
 - keep calm.
*/

struct

模拟题,直接模拟即可。我写了 \(4.0\) K/ll

赛时代码
#include <bits/stdc++.h>

using namespace std;

#define de(x) cout<<#x<<"="<<x<<endl

using ll = long long;

const int N = 1e2+2;

struct node {
    int k,f;
    vector<int> ch;
    vector<string> nms;
    vector<pair<ll,ll> > mm;
    string ty;
    string nm;
    ll siz,dq;
    ll ml,mr;
    ll fd(string s){
        for (int i=0; i<k; i++){
            if (nms[i]==s){
                return i;
            }
        }
        return -1;
    }
} e[N+5];

struct memory {
    ll l,r,ty;
    string nm;
} q[N+5];

ll tot,mem,ctmem;
unordered_map<string,int> mp;
unordered_map<string,int> nmp;

void create_struct(){
    string nme;
    cin>>nme;
    mp[nme]=++tot;
    cin>>e[tot].k;
    e[tot].ch.resize(e[tot].k);
    e[tot].nms.resize(e[tot].k);
    e[tot].mm.resize(e[tot].k);
    ll mx=0,sum=0;
    for (int i=0; i<e[tot].k; i++){
        string ty;
        cin>>ty;
        cin>>e[tot].nms[i];
        e[tot].ch[i]=mp[ty];
        ll dqq=e[e[tot].ch[i]].dq;
        ll szz=e[e[tot].ch[i]].siz;
        mx=max(mx,dqq);
        sum=((sum+dqq-1)/dqq)*dqq;
        e[tot].mm[i].first=sum;
        e[tot].mm[i].second=sum+szz-1;
      //  cout<<sum<<"~";
        sum=sum+szz;
      //  cout<<sum-1<<endl;
    }
    sum=((sum+mx-1)/mx)*mx;
    e[tot].siz=sum;
    e[tot].dq=mx;
    cout<<sum<<" "<<mx<<endl;
}

void create_var(){
    string ty,nme;
    cin>>ty>>nme;
    int typ=mp[ty];
    ll cm=mem;
    cm=((cm+e[typ].dq-1)/e[typ].dq)*e[typ].dq;
    cout<<cm<<endl;
    q[++ctmem].l=cm;
    q[ctmem].r=cm+e[typ].siz-1;
    q[ctmem].nm=nme;
    q[ctmem].ty=typ;
    nmp[nme]=ctmem;
    mem=e[typ].siz+cm;
}

void visit_var(){
    string s;
    cin>>s;
    int i=0;
    string bt;
    while (i<s.size() && s[i]!='.'){
        bt.push_back(s[i++]);
    }
    ll ct=nmp[bt];
    ll lb=q[ct].l,cty=q[ct].ty;
    i++;
    while (i<s.size()){
        string t;
        while (i<s.size() && s[i]!='.'){
            t.push_back(s[i++]);
        }
        i++;
        ll id=e[cty].fd(t);
        lb=lb+e[cty].mm[id].first;
        cty=e[cty].ch[id];
    }
    cout<<lb<<endl;
}

void visit_addr(){
    ll ad;
    cin>>ad;
    string dt="~",res;
    int ii;
    for (ii=1; ii<=ctmem; ii++){
        if (q[ii].l<=ad && ad<=q[ii].r){
            dt=q[ii].nm;
            break;
        }
    }
    if (dt=="~"){
        cout<<"ERR"<<endl;
        return;
    }
  //  cout<<"OK"<<endl;
    res+=dt;
    ll cty=q[ii].ty,lb=q[ii].l,rb=q[ii].r;
  //  cout<<res<<endl;
    while (e[cty].k){
        res.push_back('.');
     //   cout<<res<<endl;
        ll id=-1;
        for (int i=0; i<e[cty].k; i++){
            if (e[cty].mm[i].first+lb<=ad){
                id=i;
            }
        }
        if (id<0){
            cout<<"ERR"<<endl;
            return;
        }
        if (e[cty].mm[id].second+lb<ad){
            cout<<"ERR"<<endl;
            return;
        }
        res+=e[cty].nms[id];
        lb=e[cty].mm[id].first+lb;
        rb=lb+e[e[cty].ch[id]].siz-1;
        cty=e[cty].ch[id];
    }
  //  cout<<"OKK"<<","<<cty<<endl;
    if (e[cty].f){
        cout<<res<<endl;
    }
    else{
        cout<<"ERR"<<endl;
    }
}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);

    //freopen("struct.in","r",stdin);
//    freopen("struct.out","w",stdout);
    mp["byte"]=1;
    mp["short"]=2;
    mp["int"]=3;
    mp["long"]=4;
    e[++tot].f=1;
    e[tot].siz=e[tot].dq=1;
    e[tot].nm="byte";
    e[++tot].f=1;
    e[tot].siz=e[tot].dq=2;
    e[tot].nm="short";
    e[++tot].f=1;
    e[tot].siz=e[tot].dq=4;
    e[tot].nm="int";
    e[++tot].f=1;
    e[tot].siz=e[tot].dq=8;
    e[tot].nm="long";
    int q;
    cin>>q;
    while (q--){
        int op;
        cin>>op;
        if (op==1){
            create_struct();
        }
        else if (op==2){
            create_var();
        }
        else if (op==3){
            visit_var();
        }
        else{
            visit_addr();
        }
    }
    return 0;
}

/*
 - int/long long?
 - memory?
 - init for multiple cases?
 - modular?
 - read the problem statement.
 - keep calm.
*/

tree

思路好像没有假,但是写挂了。

考虑先二分,再 check 答案。先给每个点求出一个值:它最多在多少树之后。然后 dp/贪心 看看有没有不合法即可。

posted @ 2023-10-22 11:34  SFlyer  阅读(200)  评论(2编辑  收藏  举报