ABC415

被C卡了
不是为啥啊

C

题意:
判断是否能够通过状态转移使0转移到2^n-1
其中有些状态无法转移
思路:
这题要用dp。:(
dp[0]=1,如果状态可以被转移,那么按位判断

void solve(){
    int n;cin>>n;
    string s;cin>>s;
    int m=s.size();
    s=" "+s;
    vector<int>vis(m+1);
    vector<int>dp((1ll<<n)+1);
    rep(i,1,m){
        if(s[i]=='1')vis[i]=1;
    }
    dp[0]=1;

    for(int i=1;i<(1ll<<n);i++){
        if(vis[i])continue;
        for(int j=0;j<n;j++){
            if(i&(1ll<<j)){
                if(dp[(i^(1ll<<j))])dp[i]=1;
            }
        }
    }
    if(dp[(1ll<<n)-1]){
        cout<<"Yes"<<endl;
    }else cout<<"No"<<endl;
}

E

题意:
给定一个矩阵,每次要么向下走要么向右走。每走一步,先拿矩阵值,再消耗px
求让每一步操作后值大小都不小于0的最小初始值
思路:
发现求的是从左上到右下中路径的谷值

可以使用反向dp。因为如果正向dp,初始值是待求不确定的

记dp[i][j]为从(i,j)->(n,m)所需的额外初值

为了使答案最小,最后操作后剩余值一定为0

因此反向dp初始值为0

每次操作相当于拿了px值,再消耗矩阵值

如果dp[i][j]<=0,意味着不需要消耗额外的初值。因为一开始钱不可能为负的,所以此时dp[i][j]=0
如果dp[i][j]>0,意味着需要消耗额外的初值。

考虑转移,显然dp[i][j]->dp[i][j-1],dp[i-1][j]

需要使dp[i][j-1],dp[i-1][j]尽可能小

答案为dp[1][1]

int n,m;
void solve(){
    cin>>n>>m;
    vector<vector<int>>g(n+1,vector<int>(m+1));rep(i,1,n)rep(j,1,m)cin>>g[i][j];
    vector<vector<int>>f(n+1,vector<int>(m+1,1e18));
    vector<int>p(n+m+1);rep(i,1,n+m-1)cin>>p[i];
    f[n][m]=0;

    for(int i=n;i>=1;i--){
        for(int j=m;j>=1;j--){
            f[i][j]+=p[i+j-1]-g[i][j];
            f[i][j]=max(0ll,f[i][j]);

            f[i-1][j]=min(f[i-1][j],f[i][j]);
            f[i][j-1]=min(f[i][j-1],f[i][j]);
        }
    }
    cout<<f[1][1]<<endl;
    
}

F

用线段树维护区间相同字符最大长度

struct SGT{
    #define ls p<<1
    #define rs p<<1|1
    string s;
    struct node{
        int l,r;
        int lv,rv;
        int len,ans;
        node():l(0),r(0),lv(0),rv(0),len(0),ans(0){}
    }tr[maxn<<2];

    void pushup(int p){
        if(tr[ls].lv==tr[ls].len&&s[tr[ls].r]==s[tr[rs].l]){
            tr[p].lv=tr[ls].len+tr[rs].lv;
        }else tr[p].lv=tr[ls].lv;
        if(tr[rs].rv==tr[rs].len&&s[tr[ls].r]==s[tr[rs].l]){
            tr[p].rv=tr[rs].len+tr[ls].rv;
        }else tr[p].rv=tr[rs].rv;

        tr[p].ans=max(tr[ls].ans,tr[rs].ans);
        if(s[tr[ls].r]==s[tr[rs].l]){
            tr[p].ans=max(tr[p].ans,tr[ls].rv+tr[rs].lv);
        }
        tr[p].ans=max({tr[p].ans,tr[ls].lv,tr[rs].rv});
    }

    void build(int p,int l,int r){
        tr[p].l=l;tr[p].r=r;tr[p].len=(r-l+1);
        if(l==r){
            tr[p].lv=tr[p].rv=tr[p].ans=1;return;
        }
        int mid=l+r>>1;
        build(ls,l,mid);build(rs,mid+1,r);
        pushup(p);
    }

    void add(int p,int pos,char ch){
        if(tr[p].l==tr[p].r&&tr[p].l==pos){
            s[pos]=ch;return;
        }
        int mid=tr[p].l+tr[p].r>>1;
        if(pos<=mid)add(ls,pos,ch);
        else add(rs,pos,ch);
        pushup(p);
    }

    node query(int p,int l,int r){
        if(l<=tr[p].l&&tr[p].r<=r)return tr[p];

        int mid=tr[p].l+tr[p].r>>1;
        if(r<=mid)return query(ls,l,r);
        if(l>mid)return query(rs,l,r);
        
        node L=query(ls,l,r);
        node R=query(rs,l,r);
        node res;
        res.l=L.l;res.r=R.r;
        res.len=L.len+R.len;
        if(L.lv==L.len&&s[L.r]==s[R.l])res.lv=L.len+R.lv;
        else res.lv=L.lv;
        if(R.rv==R.len&&s[L.r]==s[R.l])res.rv=R.len+L.rv;
        else res.rv=R.rv;
        res.ans=max(L.ans,R.ans);
        if(s[L.r]==s[R.l]){
            res.ans=max(res.ans,L.rv+R.lv);
        }
        res.ans=max({res.ans,res.lv,res.rv});
        return res;
    }
}seg;
void solve(){
    int n,m;cin>>n>>m;
    string s;cin>>s;
    s=" "+s;
    seg.s=s;
    seg.build(1,1,n);
    while(m--){
        int opt;cin>>opt;
        if(opt==1){
            int pos;char ch;cin>>pos>>ch;
            seg.add(1,pos,ch);
        }else{
            int l,r;cin>>l>>r;
            cout<<(seg.query(1,l,r).ans)<<endl;
        }
    }
}
posted @ 2025-07-19 22:33  Marinaco  阅读(53)  评论(0)    收藏  举报
//雪花飘落效果