AtCoder Beginner Contest 368 补题记录(A~D,F,G)

被伟大的 G 创似辣。

A

signed main(){
    int n,k;cin>>n>>k;
    F(i,1,n)cin>>a[i];
    queue<int>stk;
    G(i,n,1)stk.push(a[i]);
    while(k--){
        int t=stk.front();
        stk.push(t);
        stk.pop();
    }
    stack<int>t;
    F(i,1,n){
        t.push(stk.front());
        stk.pop();
    }
    while(t.size()){
        cout<<t.top()<<' ';
        t.pop();
    }
    cout<<'\n';
    return 0;
}

B

const int N=1000100;
int a[N];
signed main(){
    int n,k;cin>>n;
    F(i,1,n)cin>>a[i];
    int cnt=0;
    VI t;
    F(i,1,n)t.eb(a[i]);
    while(true){
        if(t.size()<2)break;
        sort(rng(t),greater<>());
        --t[0],--t[1];
        VI nw;
        for(auto &x:t)
            if(x>0)nw.eb(x);
        t.swap(nw);
        // cout<<"qwq: ";
        // for(auto &x:t)cout<<x<<' ';
        // cout<<'\n';
        ++cnt;
    }
    cout<<cnt<<'\n';
    return 0;
}

C

容易发现攻击 \(3\) 次一循环,一共对怪物攻击 \(5\) 次。所以对于 \(a_i\ge 5\) 的部分直接算,\(a_i<5\) 的部分暴力模拟。

时间复杂度为 \(O(n)\)

const int N=1000100;
int a[N];
signed main(){
    int n;cin>>n;
    F(i,1,n)cin>>a[i];
    int cnt=0;
    F(i,1,n){
        cnt+=a[i]/5*3;
        a[i]%=5;
        while(a[i]>0){
            ++cnt;
            if(cnt%3==0)a[i]-=3;
            else --a[i];
        }
    }
    cout<<cnt<<'\n';
    return 0;
}

D

这让我想起了昨天做过的某道树剖。考虑在 \(a\) 中随机钦定一个结点为根,然后以这个点为根重构整棵树。枚举 \(a\) 中每一个点,将 \(a\) 到根的简单路径上每一个点都打一个标记。最后询问总共有多少个标记即可。

这个东西可以用树剖套线段树(或者 ODT)维护,维护当前区间内总共被打了多少个标记,然后再上一个懒标记即可,但是因为树剖没有复制板子导致吃 \(3\) 发罚时。

因此总时间复杂度为 \(O(n\log^2n)\)

const int N=600100;
int n,m,s;
VI z[N];
int sz[N],dep[N],hev[N],top[N],up[N],dfn[N],back[N],a[N],xia[N];
void dfs(int u,int fa){
    sz[u]=1,dep[u]=dep[fa]+1,up[u]=fa;
    for(auto &v:z[u])if(v!=fa){
        dfs(v,u),sz[u]+=sz[v];
        xia[u]=v;
        if(sz[hev[u]]<sz[v])hev[u]=v;
    }
}
int idx;
void dfs2(int u,int Top,int fa){
    top[u]=Top;
    dfn[u]=++idx,back[idx]=u;
    if(hev[u])dfs2(hev[u],Top,u);
    for(auto &v:z[u])if(v!=fa&&v!=hev[u])
        dfs2(v,v,u);
}
int lca(int u,int v){
    while(top[u]!=top[v]){
        if(dep[top[u]]>dep[top[v]])
            u=up[top[u]];
        else
            v=up[top[v]];
    }
    if(dep[u]<dep[v])
        return u;
    return v;
}
namespace yhb{

struct qwq{
    int l,r,sum,tag;
    void init(int p){
        l=r=p;sum=0;
        tag=0;
    }
    void yhb(int v){
        sum=(r-l+1)*v;
        tag=v;
    }
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){ //pushup
    return {l.l,r.r,l.sum+r.sum,0ll};
}
void build(int l,int r,int rt){
    if(l==r)return z[rt].init(l);
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){ //pushdown
    if(z[rt].tag){
        z[rt<<1].yhb(z[rt].tag);
        z[rt<<1|1].yhb(z[rt].tag);
        z[rt].tag=0;
    }
}
void modify(int l,int r,int rt,int ll,int rr,int v){
    if(ll<=l&&r<=rr){z[rt].yhb(v);return;}
    int mid=l+r>>1;pushyhb(rt);
    if(ll<=mid)modify(l,mid,rt<<1,ll,rr,v);
    if(mid<rr)modify(mid+1,r,rt<<1|1,ll,rr,v);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query(int l,int r,int rt,int ll,int rr){
    if(ll<=l&&r<=rr)return z[rt].sum;
    int mid=l+r>>1,s=0;pushyhb(rt);
    if(ll<=mid&&mid<rr)return query(l,mid,rt<<1,ll,rr)+query(mid+1,r,rt<<1|1,ll,rr);
    if(mid<rr)return query(mid+1,r,rt<<1|1,ll,rr);
    return query(l,mid,rt<<1,ll,rr);
}
}
void lnk_modify(int u,int v,int w){
    while(top[u]!=top[v]){
        if(dep[up[top[u]]]<dep[up[top[v]]])
            swap(u,v);
        yhb::modify(1,n,1,dfn[top[u]],dfn[u],w);
        u=up[top[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    yhb::modify(1,n,1,dfn[u],dfn[v],w);
}
int lnk_query(int u,int v){
    int s=0;
    while(top[u]!=top[v]){
        if(dep[up[top[u]]]<dep[up[top[v]]])
            swap(u,v);
        s+=yhb::query(1,n,1,dfn[top[u]],dfn[u]);
        u=up[top[u]];
    }
    if(dep[u]>dep[v])swap(u,v);
    s+=yhb::query(1,n,1,dfn[u],dfn[v]);
    return s;
}

#ifndef THIS_IS_JIAOHUTI
signed main(){
    // freopen("count_in","r",stdin);freopen("count.out","w",stdout);
    ios_base::sync_with_stdio(0);cin.tie(0);
    int k;
    cin>>n>>k;F(i,1,n-1){
        int u,v;cin>>u>>v;
        Adde(u,v);
    }
    F(i,1,k)cin>>a[i];
    dfs(a[1],0),dfs2(a[1],a[1],0);
    yhb::build(1,n,1);
    F(i,1,k)lnk_modify(a[1],a[i],1);
    cout<<yhb::z[1].sum<<'\n';
}

E

咕咕咕。

F

每一个游戏之间互相独立,所以考虑求解每一个游戏的 SG 值。

对每一个 SG 值做一次记忆化 dp:

  • \(x=1\),则 \(\text{SG}(x)=0\)
  • 否则,\(\forall\ d\ s.t.\ d\mid x\),令 \(F\leftarrow x\),则 \(\text{SG}(x)=\text{Mex}(F)\)

求所有满足条件的 \(d\) 可以 Pollard-Rho 然后暴力重构做到大概是 \(O(n^\frac{4}{5}+n\ln^2n)\),但是我懒所以直接暴力分解质因数,做到了 \(O(n^\frac{3}{2})\)

const int N=600100;
int sg[N];
int SG(int x){
    if(~sg[x])return sg[x];
    VI t;
    for(int i=1;i*i<=x;++i){
        if(x%i==0&&i!=x)t.eb(SG(i));
        if(x%i==0&&i*i!=x&&x/i!=x)t.eb(SG(x/i));
    }
    unordered_set<int>se;
    for(auto &x:t)se.insert(x);
    F(i,0,1e18)if(!se.count(i)){
        return sg[x]=i;
    }
    return -1;
}
#ifndef THIS_IS_JIAOHUTI
signed main(){
    // freopen("count_in","r",stdin);freopen("count.out","w",stdout);
    // ios_base::sync_with_stdio(0);cin.tie(0);
    int n;cin>>n;
    int xr=0;
    FIN(sg);
    F(i,1,100000){
        // if(i%1000==0)cout<<i<<'\n';
        SG(i);
    }
    F(i,1,n){
        int x;cin>>x;
        xr^=sg[x];
    }
    if(xr)cout<<"Anna\n";
    else cout<<"Bruno\n";
}

#else

#define NO_MAIN
void no_main() {
    puts("pwp");
}

#endif

G

首先考虑维护一大堆线段树分别维护:

  • 每个元素最左边的 \(1\) 位置 \(i_1\)
  • 每个元素最右边的 \(1\) 位置 \(i_2\)
  • 每一段区间的和 \(i_3\)
  • 每一段区间的最大 \(b\)\(i_4\)
  • 每一段区间 \(b\) 值的最大位置 \(i_5\)

然后可以使用 \(4\) 个线段树来维护上述的所有信息。时间复杂度为 \(O(n)\)

维护完之后可以发现暴力时间复杂度正确:因为选择乘法的次数不会超过 \(\log_2 10^{18}\approx 60\),因此把所有连续 \(1\) 块暴力缩之后最多只会枚举 \(120\) 个元素。因此总的时间复杂度是 \(O(n\log n\log V)\),其中 \(V\) 是值域。

说的有点混乱,建议结合代码查看。

#
/*
#define THIS_IS_JIAOHUTI
*/
#


#include<bits/stdc++.h>
#define pb push_back
#define eb emplace_back
#ifndef THIS_IS_JIAOHUTI
#define int long long
#endif
#define F(i,x,y) for(int i=x;i<=y;++i)
#define G(i,x,y) for(int i=x;i>=y;--i)
#define FD(x,y) for(int i=x;i*i<=y;++i)
#define GD(x,y) for(int i=x;i*i>=y;--i)
#define adde(x,y) z[x].eb(y);
#define Adde(x,y) z[x].eb(y),z[y].eb(x);
#define addew(x,y,w) z[x].eb(y,w)
#define Addew(x,y,w) z[x].eb(y,w),z[y].eb(x,w)
#define FIMX(X) memset(X,0x3f,sizeof X)
#define FIMI(X) memset(X,-0x3f,sizeof X)
#define FI0(X) memset(X,0,sizeof X)
#define FIN(X) memset(X,-1,sizeof X)
#define rng(X) X.begin(),X.end()
#define PII pair<int,int>
#define PDD pair<double,double>
#define PIII tuple<int,int,int>
#define VI vector<int>
#define VII vector<PII>
#define VID vector<pair<int,double>>
#define VDD vector<PDD>
using namespace std;
const int N=600100;
int a[N],b[N];
#if 0
struct Range{
    int l,r,v;
} ;
int R[N],L[N];
//R[i]: i zui you bian de yi ge b shu zu bu shi 1 de wei zhi de zuo bian yi ge wei zhi 
namespace t1{

struct qwq{
    int l,r,mx,tag;
    void init(int p){
        l=r=p;
        mx=L[p];
        tag=-1;
    }
    void yhb(int v){
        mx=(r-l+1)*v;
        tag=v;
    }
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
    return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
    if(l==r)
        return z[rt].init(l);
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
    if(z[rt].tag!=-1){
        z[rt<<1].yhb(z[rt].tag);
        z[rt<<1|1].yhb(z[rt].tag);
        z[rt].tag=-1;
    }
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
    if(ll<=l&&r<=rr)
        return z[rt].yhb(v);
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid)
        modify1(l,mid,rt<<1,ll,rr,v);
    if(mid<rr)
        modify1(mid+1,r,rt<<1|1,ll,rr,v);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
    if(ll<=l&&r<=rr)
        return z[rt].mx;
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid&&mid<rr)
        return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
    if(mid<rr)
        return query1(mid+1,r,rt<<1|1,ll,rr);
    return query1(l,mid,rt<<1,ll,rr);
}
}
namespace t2{

struct qwq{
    int l,r,mx,tag;
    void init(int p){
        l=r=p;
        mx=R[p];
        tag=-1;
    }
    void yhb(int v){
        mx=(r-l+1)*v;
        tag=v;
    }
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
    return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
    if(l==r)
        return z[rt].init(l);
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
    if(z[rt].tag!=-1){
        z[rt<<1].yhb(z[rt].tag);
        z[rt<<1|1].yhb(z[rt].tag);
        z[rt].tag=-1;
    }
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
    if(ll<=l&&r<=rr)
        return z[rt].yhb(v);
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid)
        modify1(l,mid,rt<<1,ll,rr,v);
    if(mid<rr)
        modify1(mid+1,r,rt<<1|1,ll,rr,v);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
    if(ll<=l&&r<=rr)
        return z[rt].mx;
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid&&mid<rr)
        return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
    if(mid<rr)
        return query1(mid+1,r,rt<<1|1,ll,rr);
    return query1(l,mid,rt<<1,ll,rr);
}
}
namespace t3{

struct qwq{
    int l,r,mx,tag;
    void init(int p){
        l=r=p;
        mx=a[p];
        tag=-1;
    }
    void yhb(int v){
        mx=(r-l+1)*v;
        tag=v;
    }
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
    return {l.l,r.r,l.mx+r.mx,-1ll};
}
void build(int l,int r,int rt){
    if(l==r)
        return z[rt].init(l);
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void pushyhb(int rt){
    if(z[rt].tag!=-1){
        z[rt<<1].yhb(z[rt].tag);
        z[rt<<1|1].yhb(z[rt].tag);
        z[rt].tag=-1;
    }
}
void modify1(int l,int r,int rt,int ll,int rr,int v){
    if(ll<=l&&r<=rr)
        return z[rt].yhb(v);
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid)
        modify1(l,mid,rt<<1,ll,rr,v);
    if(mid<rr)
        modify1(mid+1,r,rt<<1|1,ll,rr,v);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
int query1(int l,int r,int rt,int ll,int rr){
    if(ll<=l&&r<=rr)
        return z[rt].mx;
    int mid=l+r>>1;
    pushyhb(rt);
    if(ll<=mid&&mid<rr)
        return query1(l,mid,rt<<1,ll,rr)+query1(mid+1,r,rt<<1|1,ll,rr);
    if(mid<rr)
        return query1(mid+1,r,rt<<1|1,ll,rr);
    return query1(l,mid,rt<<1,ll,rr);
}
}
//t1 维护 L
//t2 维护 R
//t3 维护 a
//b 不需要维护
#endif
struct qwq{
    int l,r,cnt,ch,mx;
    void init(int p){
        l=r=p;
        mx=a[p];
        ch=b[p];
        if(b[p]!=1)
            cnt=1;
        else
            cnt=0;
    }
}z[N<<2];
qwq operator+(const qwq&l,const qwq&r){
    return {l.l,r.r,l.cnt+r.cnt,0ll,l.mx+r.mx};
}
void build(int l,int r,int rt){
    if(l==r)
        return z[rt].init(l);
    int mid=l+r>>1;
    build(l,mid,rt<<1);
    build(mid+1,r,rt<<1|1);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void modify1(int l,int r,int rt,int p,int v){
    if(l==r){
        z[rt].mx=v;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid)
        modify1(l,mid,rt<<1,p,v);
    else
        modify1(mid+1,r,rt<<1|1,p,v);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
void modify2(int l,int r,int rt,int p,int x){
    if(l==r){
        z[rt].ch=x;
        if(x!=1)z[rt].cnt=1;
        else z[rt].cnt=0;
        return;
    }
    int mid=l+r>>1;
    if(p<=mid)
        modify2(l,mid,rt<<1,p,x);
    else
        modify2(mid+1,r,rt<<1|1,p,x);
    z[rt]=z[rt<<1]+z[rt<<1|1];
}
PII query1(int l,int r,int rt,int ll,int rr){
    if(l==r){
        if(z[rt].cnt)return {l,rt};
        else return {0,0};
    }
    int mid=l+r>>1;
    if(ll<=l&&r<=rr){
        if(z[rt<<1].cnt)
            return query1(l,mid,rt<<1,ll,rr);
        else
            return query1(mid+1,r,rt<<1|1,ll,rr);
    }else{
        PII z={0,0};
        if(ll<=mid)
            z=query1(l,mid,rt<<1,ll,rr);
        if(mid<rr&&!z.first) z=query1(mid+1,r,rt<<1|1,ll,rr);
        return z;
    }
}
int query2(int l,int r,int rt,int ll,int rr){
    if(ll<=l&&r<=rr)
        return z[rt].mx;
    int mid=l+r>>1;
    if(ll<=mid&&mid<rr)
        return query2(l,mid,rt<<1,ll,rr)+query2(mid+1,r,rt<<1|1,ll,rr);
    if(ll<=mid)
        return query2(l,mid,rt<<1,ll,rr);
    return query2(mid+1,r,rt<<1|1,ll,rr);
}
#ifndef THIS_IS_JIAOHUTI
signed main(){
    // freopen("count_in","r",stdin);freopen("count.out","w",stdout);
    ios_base::sync_with_stdio(0);cin.tie(0);
    int n;cin>>n;
    F(i,1,n)cin>>a[i];
    F(i,1,n)cin>>b[i];
    build(1,n,1);int q;cin>>q;
    while(q--){
        int o;cin>>o;
        if(o==1){
            int l,r;cin>>l>>r;
            modify1(1,n,1,l,r);
        }else if(o==2){
            int l,r;cin>>l>>r;
            modify2(1,n,1,l,r);
        }else{
            int l,r;cin>>l>>r;
            int mx=0;
            while(l<=r){
                auto T=query1(1,n,1,l,r);
                if(!T.first)break;
                // cout<<"qwq "<<T.first<<' '<<T.second<<'\n';
                if(T.first!=l)mx+=query2(1,n,1,l,T.first-1);
                else;
                mx=max(mx*z[T.second].ch,mx+z[T.second].mx);
                l=T.first+1;
            }
            if(l<=r)
                mx+=query2(1,n,1,l,r);
            cout<<mx<<'\n';
        }
    }
}

#else

#define NO_MAIN
void no_main() {
    puts("pwp");
}

#endif
posted @ 2024-08-24 22:09  yhbqwq  阅读(107)  评论(0编辑  收藏  举报