AtCoder Beginner Contest 450题解

D - Minimize Range

注意到取模结果都差不多。只用考虑最大和最小。

int n,k,a[N],b[N];deque<int>dq;
void solve(){
    cin>>n>>k;
    int x;
    up(i,1,n){
        cin>>a[i];
        a[i]%=k;
    }
    sort(a+1,a+1+n);
    up(i,1,n)dq.push_back(a[i]);
    int ans=inf;
    up(i,1,n){
        ans=min(ans,dq[n-1]-dq[0]);
        int u=dq.back();
        dq.pop_back();
        dq.push_front(u-k);
    }
    cout<<ans;
}

E - Fibonacci String

简单递归喵。

void solve(){
    string X, Y;
    cin >> X >> Y;
    const int M = 26;
    const int L = 100;
    vector<array<ll, M>> base(L);
    vector<vector<array<ll, M>>> p(2);
    vector<ll> len(L);
    auto f = [&](int ind, string S) -> void {
        len[ind] = S.size();
        rep(i, 0, M) base[ind][i] = 0;
        p[ind].push_back(base[ind]);
        for (auto c : S){
            base[ind][c - 'a']++;
            p[ind].push_back(base[ind]);
        }
    };
    f(0, X);
    f(1, Y);
    rep(i, 2, L){
        len[i] = min(ILL, len[i - 1] + len[i - 2]);
        rep(j, 0, M) base[i][j] = base[i - 1][j] + base[i - 2][j];
    }
    // vec_out(len);
    auto g = [&](auto self, ll l, int ind, int c) -> ll {
        // cout << ind << " " << l << endl;
        if (ind < 2){
            return p[ind][l][c];
        }
        if (len[ind] == l) return base[ind][c];
        ll tmp = min(l, len[ind - 1]);
        ll res = self(self, tmp, ind - 1, c);
        l -= tmp;
        if (l > 0) res += self(self, l, ind - 2, c);
        return res;
    };
    int Q;
    cin >> Q;
    while (Q--){
        ll l, r;
        char c;
        cin >> l >> r;
        cin >> c;
        cout << g(g, r, L - 1, c - 'a') - g(g, l - 1, L - 1, c - 'a') << "\n";
    }
}

F - Strongly Connected 2

虽然是个图问题,但是实际上是一条链。我们只用简单的考虑有多少种选择方法可以选出线段能够覆盖整个区间。

我们钦定 \(dp[i][j]\) 表示进入第 \(i\) 条线段,最多到 \(j\) 的答案。很容易有转移公式。

然后进行线段树优化 \(dp\)

int n,m;
pii a[N];
struct SegmentTree{
    struct node{
        int l,r,sum;
        int tag;
    }tr[N<<2];
    void push_up(int k){
        tr[k].sum=(tr[lc].sum+tr[rc].sum)%mod;
    }
    void build(int k,int l,int r){
        tr[k]={l,r,0,1};
        if(l==r){
            if(l==1)tr[k].sum=1;
            return;
        }
        int mid=(l+r)>>1;
        build(lc,l,mid);
        build(rc,mid+1,r);
        push_up(k);
    }
    void push_down(int k){
        if(tr[k].tag!=1){
            tr[lc].tag=tr[lc].tag*tr[k].tag%mod;
            tr[rc].tag=tr[rc].tag*tr[k].tag%mod;
            tr[lc].sum=tr[lc].sum*tr[k].tag%mod;
            tr[rc].sum=tr[rc].sum*tr[k].tag%mod;
            tr[k].tag=1;
        }
    }
    int asksum(int k,int l,int r){
        if(tr[k].l>=l&&tr[k].r<=r)return tr[k].sum;
        push_down(k);
        int mid=(tr[k].l+tr[k].r)>>1,res=0;
        if(mid>=l)res+=asksum(lc,l,r);
        if(mid<r)res+=asksum(rc,l,r);
        return res%mod;
    }
    void plus(int k,int l,int r){
        if(l>r)return;
        if(tr[k].l>=l&&tr[k].r<=r){
            tr[k].sum=(tr[k].sum)*2%mod;
            tr[k].tag=tr[k].tag*2%mod;
            return;
        }
        push_down(k);
        int mid=(tr[k].l+tr[k].r)>>1,res=0;
        if(mid>=l)plus(lc,l,r);
        if(mid<r)plus(rc,l,r);
        push_up(k);
    }
    void add(int k,int l,int r,int val){
        if(l>r)return;
        if(tr[k].l>=l&&tr[k].r<=r){
            tr[k].sum=(tr[k].sum+val)%mod;
            return;
        }
        push_down(k);
        int mid=(tr[k].l+tr[k].r)>>1,res=0;
        if(mid>=l)add(lc,l,r,val);
        if(mid<r)add(rc,l,r,val);
        push_up(k);
    }
}T;
void solve(){
    cin>>n>>m;
    int u,v;
    up(i,1,m){
        cin>>u>>v;
        a[i]={u,v};
    }
    sort(a+1,a+1+m);
    T.build(1,1,n);
    //cout<<T.tr[1].sum<<endl;
    up(i,1,m){
        T.plus(1,1,a[i].fi-1);
        T.plus(1,a[i].se+1,n);
        int sum=T.asksum(1,a[i].fi,a[i].se);
        //cout<<a[i].fi<<" "<<a[i].se<<endl;cout<<sum<<endl;
        T.add(1,a[i].se,a[i].se,sum);
    }
    cout<<T.asksum(1,n,n);
}
posted @ 2026-03-24 21:21  LiQXing  阅读(21)  评论(0)    收藏  举报