11.19与11.20笔记

Problem - A - Codeforces

类似合并石子,但是合并的代价是\(\max(x,y)\)
对复杂度要求高。
因为每个元素只可能比之前更大,我们最小的数两边的数提前被取一定更优。

int n,pre[N],nxt[N];
struct node{
    int key,pos;
}a[N];
int b[N];
inline bool cmp(node x,node y){
    return x.key<y.key;
}
inline void clear(){
    
}
inline void solve(){
    cin>>n;
    up(i,1,n){
        a[i]={read(),i};
        b[i]=a[i].key;
        pre[i]=i-1;
        nxt[i]=i+1;
    }
    pre[1]=n;nxt[n]=1;
    sort(a+1,a+1+n,cmp);
    int ans=0;
    up(i,1,n-1){
        ans+=min(b[pre[a[i].pos]],b[nxt[a[i].pos]]);
        nxt[pre[a[i].pos]]=nxt[a[i].pos];
        pre[nxt[a[i].pos]]=pre[a[i].pos];
    }
    cout<<ans<<endl;
}
signed main(){
    int T;
    cin>>T;
    while(T--){
        clear();
        solve();
    }
    return 0;
}         

Problem - B - Codeforces

很难绷的一道题
让你计算多集合的数量。

首先,很明显的一点。这道题和数无关,只和数的数量有关。
比如 1 1 1 1 2 2 2 3 3 4和2 2 2 2 3 3 3 4 4 1 等价。
然后,我们可以这么依次对每个数进行处理。我们考虑每个数是作为特征数还是非特征数。
那么特征数会覆盖掉非特征数。
我们可以 一个一个数的往下递推。
比如我们看1,可以先分为特证数和非特征数。

1  1  
     1  1

我们考虑先不分组,那么1的分配有5种

但是很容易发现,如果我们把1全放在特证数上。
1111,我们这种情况加上分组则可以为s提供1的各种数量(0除外),而且这样的话,为之后的数提供了更多隐藏的位置,更优。

所以每次我们都只用考虑(0,cnt)和(cnt,0)的情况。

然后就可以考虑背包。

int n,a[N],cnt[N],maxl,f[N];
inline void clear(){
    up(i,1,n)a[i]=0;
    up(i,1,n)f[i]=0;
    maxl=0;
    up(i,1,n)cnt[i]=0;
}
signed main(){
    int T;
    cin>>T;
    while(T--){
        clear();
        cin>>n;
        up(i,1,n){
            cin>>a[i];
            cnt[a[i]]++;
            maxl=max(maxl,cnt[a[i]]);
        }
        f[0]=1;
        up(i,1,n){
            if(cnt[i]){
                dn(j,n,cnt[i]){
                    f[j]=(f[j]+cnt[i]*f[j-cnt[i]])%mod;
                }
            }
        }
        int ans=0;
        for(int i=maxl;i<=n;i++)ans=(ans+f[i])%mod;
        cout<<ans<<endl;
    }
    return 0;
}

posted @ 2025-11-21 12:07  LiQXing  阅读(3)  评论(0)    收藏  举报