小白月赛99FG

F-自爆机器人_牛客小白月赛99 (nowcoder.com)

假设从个点中的某个点\(\color{#50F}{a_k}\)设立墙,将机器人往左弹 , 中间过程不考虑,其一定会回到\(\color{#50F}{m}\)点,称其为\(\color{#50F}{k}\)点的一个往返,其距离为 \(\color{#50F}{a_k - a_{i} , i \in [ 1 , k -1]}\) , 每个点都可以有多个往返,现在考虑中间的过程不难发现中间的过程也是又很多个往返组成 ,由于往返的位移为零,题目要求位移为\(\color{#50F}{n}\)所以还要加上一个向右的大小为\(\color{#50F}{n}\)的位移,所以总共的伤害为\(\color{#50F}{min(\Sigma_{i = 1}^{k}f(a_i) + n, t) , f(a_i) 为a_i往返距离和}\)

\(\color{#50F}{k}\)的每个往返必定包含 \(\color{#50F}{a_k - a_{k-1}}\) , 所以每个往返可以只统计\(\color{#50F}{a_k - a_{k-1}}\),其余距离留计算其他往返时统计 , 列如\(\color{#50F}{a_5 - a_{1},可以拆成 a_5 - a_4 , a_4 - a_3 , a_3 - a_2 , a_2 - a_1 } 将5的往返拆成了 5 , 4 , 3 , 2 ,1 的距离为a_x - a_{x-1}往返\)

很容易就能想到用完全背包解决,但我看\(\color{#50F}{m}\)的范围是\(\color{#50F}{[1 , 2*1e^5]}\) 算得复杂度为\(\color{#50F}{m* n}\)迟迟不敢写,后来看题解发现\(\color{#50F}{a_k - a_{k-1}}\)两两不相同也最多只有\(\color{#50F}{\sqrt[2]{n}}\)种可能 ,所以复杂度为\(\color{#50F}{\sqrt[2]{n}* m}\)

#include "bits/stdc++.h"
using namespace std ;
#define int long long 
#define pll pair<int , int>
const int N = 1e6 + 9 ;
int n , m , t ;
void solve( ) {
    cin >> n >> m >> t ;
    vector< int > c , d ;
    vector< bool > vis( t + 9) ;
    vis[0] = 1 ;
    for( int i = 1 ; i <= m ; i ++ ) {
        int x ;
        cin >> x ;
        c.push_back(x) ;
    }
    sort(c.begin() , c.end()) ;
    for( int i = 1 ; i < m ;i ++ ) {
        d.push_back(c[i] - c[i-1]) ;
    }
    sort(d.begin() , d.end()) ;
    d.erase(unique(d.begin() , d.end()) ,d.end()); 
    for( auto x : d ) {
        for( int i = x ; i <= t ; i ++ ) {
            vis[i] = max( vis[i - x] , vis[i]) ;
        }
    }
    int ans = 0 ;
    for( int i = t ; i >= 0 ; i -- ) {
        if( vis[i] && (i *2 + n <= t )) {
            ans = i*2 + n ;
            break;
        }
    }
    cout << ans << '\n' ;
}

signed main( ) {
    ios::sync_with_stdio(false) ,cin.tie(0) ,cout.tie(0) ;
    int _ = 1 ;
    cin >> _ ;
    while( _ -- ) {
        solve( ) ;
    }
}

G-大鱼吃小鱼_牛客小白月赛99 (nowcoder.com)

离散化,统计每个时间鱼种类,用递推的思想,假设当前时间为 i ,并且统计好了鱼的种类,计算时间为i +1时鱼的种类时只要减去 右端点为l的鱼,加上左端点为l的鱼,即可

#include "bits/stdc++.h"
using namespace std ;
#define lbt(x) x & -x 
#define int long long 
#define pll pair<int , int>
const int N = 1e6 + 9 ;
int n , w , su[N] ;
struct fish{
    int l , r , a ;
}x[N] ;
void add( int i  ,int r ) {
    while( i < n*2 ) su[i] += r , i += lbt(i) ;
}
int sum( int i ) {
    int res = 0 ;
    while( i ) res += su[i] , i -= lbt(i) ;
    return res ;
}
void solve( ) {
    vector<int>c ;// 离散化 质量
    vector<int>s ;//离散化 时间点
    cin >> n >> w ;
    memset( su , 0 , sizeof(int)*(n*2) ) ;
    vector<vector<int>> r( n*3) ; 
    vector<vector<int>> l( n*3) ; 
    for( int i = 1 ; i <= n ; i ++ ){
        cin >> x[i].l >> x[i].r >> x[i].a , c.push_back(x[i].a);
        s.push_back(x[i].l) ;
        s.push_back(x[i].r) ;
    }
    sort( c.begin() , c.end() ) ;
    c.erase(unique(c.begin() , c.end()) , c.end()) ;
    sort( s.begin() , s.end() ) ;
    s.erase(unique(s.begin() , s.end()) , s.end()) ;
    auto find = [](vector<int> &c , int x ) -> int {
        return lower_bound(c.begin(), c.end() , x ) - c.begin() + 1;
    } ;
    for( int i = 1 ; i <= n ;i ++ ) {
        x[i].l = find( s , x[i].l ) ;
        x[i].r = find( s , x[i].r ) ;
        r[x[i].r].push_back(x[i].a) ;
        l[x[i].l].push_back(x[i].a) ;
    }
    set<int , greater<int> >f ;
    map<int , int > g ;
    int ans = w ;
    for( int i = 1 ; i <= n*2 ;i ++ ) {
        for( auto x : l[i] ) {
            f.insert(x) ;
            g[x] ++ ;
            add( find( c, x) , x ) ;
        }
        for( auto x : r[i] ) {
            g[x] -- ;
            if(g[x] == 0) {
                f.erase(x);
                g.erase(x);
            }
            add( find( c, x) , -x ) ;
        }
        int v = w ;
        while( true ) {
            if(f.lower_bound(v) == f.end()) break;
            int x = find( c , *f.lower_bound(v));
            if( v == sum(x) + w ) break; 
            v = sum(x) + w;
        }
        ans = max( ans , v ) ;
    }
    cout << ans << '\n' ;
}

signed main( ) {
    ios::sync_with_stdio(false) ,cin.tie(0) ,cout.tie(0) ;
    int _ = 1 ;
    cin >> _ ;
    while( _ -- ) {
        solve( ) ;
    }
}
posted @ 2024-08-26 20:58  wbs__HWX  阅读(40)  评论(0)    收藏  举报