CSP-S模拟14(UU Round#2)

CSP-S模拟14(UU Round#2)

T1 100pts T2 0pts(哎呀呀,骇死我力) T3 10pts rk7

T1 划分序列(divide)

原题 : CF1919C - Grouping Increases

CF1919C Grouping Increases

题目描述

给定一个大小为 \(n\) 的数组 \(a\)。你需要按照以下过程计算你的惩罚值:

  1. 将数组 \(a\) 分成两个(可能为空)子序列 \(^\dagger\) \(s\)\(t\),使得 \(a\) 的每个元素都属于 \(s\)\(t^\ddagger\)
  2. 对于一个大小为 \(m\) 的数组 \(b\),定义数组 \(b\) 的惩罚值 \(p(b)\) 为满足 \(b_i < b_{i+1}\) 的下标 \(i\)\(1 \leq i \leq m-1\))的数量。
  3. 你最终获得的总惩罚值为 \(p(s) + p(t)\)

如果你最优地执行上述过程,求你能获得的最小惩罚值。

\(^\dagger\) 序列 \(x\) 是序列 \(y\) 的子序列,如果 \(x\) 可以通过从 \(y\) 中删除若干(可能为零或全部)元素得到。

\(^\ddagger\) 一些将数组 \(a=[3,1,4,1,5]\) 分成 \((s,t)\) 的合法方式有 \(([3,4,1,5],[1])\)\(([1,1],[3,4,5])\)\(([\,],[3,1,4,1,5])\),而一些不合法的方式有 \(([3,4,5],[1])\)\(([3,1,4,1],[1,5])\)\(([1,3,4],[5,1])\)

第一眼求最小惩罚值,dp 和 贪心都可做 ,那咋搞呢?

dp的状态是2维的 ,不太好转移, \(O(n^2)\) - > $ O(nlog(n)) $ 似乎需要用线段树,码量较大 ,所以考虑贪心

我们考虑什么时候能使答案最小:

这里记lastl , lastr的意思是 两个序列中最后一个元素

\(a[i]\) \(>=\) \(a[i - 1]\) 时 :

  1. 如果lastl 和 lastr 都能让 \(a[i]\) 不产生贡献 我们肯定先把小的更新掉,大的留给后面,一定更优

  2. 否则的话,我们将能 \(lastr\)\(lastl\) 中比 \(a[i]\) 大的那个更新掉

\(a[i]\) \(<\) \(a[i - 1]\) 时 :

方案和上面类似

  1. 如果lastl 和 lastr 都能让 \(a[i]\) 产生贡献 , 那么我们肯定让 两者更小的更新 , ans++

  2. 否则的话 , 我们像上面一样同时考虑没有贡献的情况就ok了

体感难度黄左右,但是线段树优化dp的做法得有绿

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 20 ; 
int a[N] , n , T ; 
int main(){
    freopen("divide.in","r",stdin);
    freopen("divide.out","w",stdout);
    ios :: sync_with_stdio(false);
    cin.tie(0) , cout.tie(0);
    cin >> T ;
    while(T--){
        cin >> n ; 
        for(int i = 1 ; i <= n ; i++){
            cin >> a[i] ; 
        }
        int lastl = a[1] , lastr = 0x3f3f3f3f , ans = 0 ; 
        for(int i = 2 ; i <= n ; i++){
            if( a[i] > a[i - 1] ){
                if(lastl >= a[i]){
                    lastl = a[i] ; 
                }
                else if( lastr >= a[i] ){
                    lastr = a[i] ; 
                }
                else{
                    if( lastr < lastl ){
                        lastr = a[i];
                        ans++;
                    }
                    else{
                        lastl = a[i];
                        ans++;
                    }
                }
            }
            else if( a[i] <= a[i - 1] ){
                if(lastl >= a[i] and lastr >= a[i]){
                    if( lastl >= lastr ){
                        lastr = a[i] ;
                    } 
                    else{
                        lastl = a[i] ;
                    }
                }
                else if( lastl >= a[i] ){
                    lastl = a[i] ; 
                }
                else{
                    lastr = a[i] ; 
                }
            }
        }
        cout << ans << endl ;
    }
    return 0;
}

T2 ZZH与背包(knapsack)

ZZH和背包

哎呀呀骇死我力这个题

本来这个题我秒出思路结果看错数据范围了,喜提0pts(数组开大了)

逆天赛时错解 数组开大MLE了qwq , \(O(nV)\) , 背包求方案 + 前缀和优化

#include<bits/stdc++.h>
using namespace std;
#define int long long 
const int N = 60 ;
const int M = 1e8 + 10 ; 
int a[N] , sum[M] , f[M] , L[910] , R[910] , cnt , n , q , l , r ;  
signed main(){
    freopen("knapsack.in","r",stdin);
    freopen("knapsack.out","w",stdout);
    ios :: sync_with_stdio(false);
    cin.tie(0) , cout.tie(0);
    cin >> n >> q ; 
    if( q == 0 ){
        return 0 ; 
    }
    for(int i = 1 ; i <= n ; i++){
        cin >> a[i] ; 
    }
    int cnt = 0 ; 
    for(int i = 1 ; i <= q ; i++){
        cin >> L[i] >> R[i] ; 
        cnt = max( cnt , R[i]) ;
    }
    f[0] = 1;
    for(int i = 1 ; i <= n ; i++){
        for(int j = cnt ; j >= a[i] ;j--){
            f[j] += f[j - a[i]];
        }
    }
    for(int i = 1 ; i <= cnt ; i++)sum[i] = sum[i - 1] + f[i] ; 
    for(int i = 1 ; i <= q ; i++){
        cout << sum[R[i]] - sum[L[i] - 1] << endl ; 
    }
    return 0 ;
}

n <= 40 显然可以meet in the middle

懒得讲了,直接贴代码

#include<bits/stdc++.h>
using namespace std;
#define int long long 
int n , q ;
int a[60] , tt1 , tt2, l , r , mid ; 
int res1[1050000] ,res2[1050000] ;
inline void dfs1(int x , int sum){
    if( x > mid ){
        res1[++tt1] = sum ;
        return ; 
    }
    dfs1(x + 1 , sum);
    dfs1(x + 1 , sum + a[x]);
}

inline void dfs2(int x , int sum){
    if( x > n ){
        res2[++tt2] = sum ;
        return ; 
    } 
    dfs2(x + 1 , sum);
    dfs2(x + 1 , sum + a[x]);
}

signed main(){
    // freopen("data.in","r",stdin);
    freopen("knapsack.in","r",stdin);
    freopen("knapsack.out","w",stdout);
    ios :: sync_with_stdio(false);
    cin.tie(0) , cout.tie(0);
    cin >> n >> q ; 
    for(int i = 1 ; i <= n ; i++){
        cin >> a[i] ; 
    }
    mid = n / 2 ; 
    dfs1(1 , 0);
    dfs2(mid + 1 , 0 );
    sort( res1 + 1 , res1 + 1 + tt1 );
    sort( res2 + 1 , res2 + 1 + tt2 );  
	res1[tt2 + 1] = 1e18;
	res2[0] = -1e18 , res2[tt2 + 1] = 1e18;
    for(int i = 1 ; i <= q ; i++){
        cin >> l >> r ; 
		int ans = 0 ; 
        for(int p = 1 , ll = tt2 + 1 , rr = tt2 + 1; p <= tt1; ++p){
			while(res1[p] + res2[ll] >= l) --ll;
			while(res1[p] + res2[rr] > r) --rr;
			ans += rr - ll;
		} 
        cout << ans << endl ; 
    }
    return 0 ; 
}

T3

会了,懒得改

T4

不会

posted @ 2025-08-20 21:01  Nailong2357  阅读(31)  评论(3)    收藏  举报