zoukankan      html  css  js  c++  java
  • 【8.17校内测试】【模拟】【set】【网络流】

    为什么每次想的最久的题得的分数最低!!!qwqwq

    再也不在noip上尝试A*叻!!

    模拟题,先把能消的消掉,双指针从两端向中间扫描,如果头尾合并可以消,就把它消掉,最后判断一下。因为消完过后num保留的是中间的个数,要把两端加上(实际就是一个循环节的长度

    #include<iostream>
    #include<cstdio>
    #define ll long long
    using namespace std;
    
    ll n, m, k, a[100005];
    ll color[100005], num[100005], cnt, tot;
    
    int main ( ) {
        freopen ( "guass.in", "r", stdin );
        freopen ( "guass.out", "w", stdout );
        scanf ( "%I64d%I64d%I64d", &n, &m, &k );
        for ( int i = 1; i <= n; i ++ ) {
            scanf ( "%I64d", &a[i] );
            if ( !cnt || a[i] != color[cnt] ) {
                cnt ++;
                color[cnt] = a[i];
                num[cnt] = 1;
            } else    num[cnt] ++;
            if ( num[cnt] == k ) num[cnt] = 0, cnt --;
        }
        for ( int i = 1; i <= cnt; i ++ )
            tot += num[i];
        int h = 1, t = cnt;
        while ( h < t && color[h] == color[t] ) {
            if ( ( num[h] + num[t] ) % k == 0 )    h ++, t --;
            else {
                num[h] = ( num[h] + num[t] ) % k;
                num[t] = 0;
                break;
            }
        }
        ll ans = 0;
        if ( h < t ) {
            for ( int i = h; i <= t; i ++ ) ans += num[i];
            ans *= ( m - 1 );
            ans += tot;
        } else if ( h == t ) {
            if ( m * num[h] % k == 0 ) ans = 0;
            else {
                ans = tot + num[h] * ( m - 1 );
                ans -= num[h] * m - num[h] * m % k;
            }
        }
        printf ( "%I64d", ans );
        return 0;
    }
    /*
    49 3 10 2
    50 1 2 1
    51 */

    stl太强大了!!!这完全就是$set$模板题qwqwqwqwq。

    发现行数很小,m=1时直接一遍扫,m=2时枚举第一行到第二行的断点,用前缀和直接计算,也是$O(n)$复杂度。

    m=3时怎么做?在set中维护$pre[3][i]-pre[2][i]$,在枚举枚举1到2的断点时,在set中查找最优的2到3的断点,设此时只有1到2断点时答案为tmp,要使最终答案在$mod p$下最优,即尽量靠近$p-tmp-1$,在set中可以直接用lower_bound查找大于等于$p-tmp$的第一个位置,减一即为所求值的位置。还有一种情况,因为tmp和set中的值都mod了p,所以加起来不大于$2p$,直接查找最大值。两个值相比较更新答案。

    #include<iostream>
    #include<cstdio>
    #include<set>
    #define ll long long
    using namespace std;
    
    set < ll > s;
    int n, m;
    ll pre[4][100005], a[4][100005], p, dp[4][100005], S;
    
    int main ( ) {
        freopen ( "candy.in", "r", stdin );
        freopen ( "candy.out", "w", stdout );
        scanf ( "%d%d%I64d", &n, &m, &p );
        for ( int i = 1; i <= m; i ++ )
            for ( int j = 1; j <= n; j ++ ) {
                scanf ( "%I64d", &a[i][j] );
                S += a[i][j];
                pre[i][j] = ( pre[i][j-1] + a[i][j] ) % p;
            }
        if ( m == 1 ) {
            printf ( "%I64d", pre[1][n] );
        } else if ( m == 2 ) {
            ll ans = 0;
            for ( int i = 1; i <= n; i ++ )
                ans = max ( ans, ( ( ( pre[1][i] + pre[2][n] ) % p - pre[2][i-1] ) % p + p ) % p );
            printf ( "%I64d", ans );
        } else if ( S < p ) {
            for ( int i = 1; i <= m; i ++ )
                for ( int j = 1; j <= n; j ++ )
                    dp[i][j] = max ( dp[i-1][j]+a[i][j], dp[i][j-1]+a[i][j] );
            printf ( "%I64d", dp[m][n] );
        } else {
            ll ans = 0;
            for ( int i = n; i >= 1; i -- ) {
                ll tmp = ( ( ( pre[1][i] + pre[2][n] ) % p - pre[2][i-1] ) % p + p ) % p;
                ll pp = ( ( ( ( pre[3][n] - pre[3][i-1] ) % p + p - pre[2][n] ) % p + p ) % p + pre[2][i-1] ) % p;
                s.insert ( pp );
                set < ll > :: iterator it, itt;
                it = s.lower_bound ( p - tmp );
                if ( it != s.begin ( ) ) it --;
                itt = s.end ( );
                if ( itt != s.begin ( ) ) itt --;
                ans = max ( ans, max ( ( tmp + *it ) % p, ( tmp + *itt ) % p ) );
            }
            printf ( "%I64d", ans );
        }
        return 0;
    }

    又是一道无脑最小割...所有点拆成出点和入点,之间正常建边,出点连向起点,流量为wi-,入点连向终点,流量为wi+,最小割即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    #define inf 0x3f3f3f3f
    using namespace std;
    
    int n, m, ru[105], chu[105], s, t;
    
    int stot = 1, nex[1000005], tov[1000005], f[1000005], h[10005], hh[10005];
    void add ( int u, int v, int ff ) {
        tov[++stot] = v;
        f[stot] = ff;
        nex[stot] = h[u];
        h[u] = stot;
        
        tov[++stot] = u;
        f[stot] = 0;
        nex[stot] = h[v];
        h[v] = stot;
    }
    
    queue < int > q;
    int dis[10005], vis[10005];
    
    bool bfs ( ) {
        memset ( dis, 0, sizeof ( dis ) );
        memset ( vis, 0, sizeof ( vis ) );
        q.push ( s ); vis[s] = 1;
        while ( !q.empty ( ) ) {
            int u = q.front ( ); q.pop ( );
            for ( int i = h[u]; i; i = nex[i] ) {
                int v = tov[i];
                if ( !vis[v] && f[i] ) {
                    dis[v] = dis[u] + 1;
                    vis[v] = 1;
                    q.push ( v );
                }
            }
        }
        return vis[t];
    }
    
    int dfs ( int u, int delta ) {
        if ( u == t ) return delta;
        int res = 0;
        for ( int i = hh[u]; i && delta; i = nex[i] ) {
            int v = tov[i];
            if ( dis[v] == dis[u] + 1 && f[i] ) {
                int dd = dfs ( v, min ( delta, f[i] ) );
                res += dd;
                f[i] -= dd;
                f[i^1] += dd;
                delta -= dd;
                hh[u] = i;
            }
        }
        return res;
    }
    
    int main ( ) {
        freopen ( "game.in", "r", stdin );
        freopen ( "game.out", "w", stdout );
        scanf ( "%d%d", &n, &m );
        s = 0, t = n * 2 + 1;
        for ( int i = 1; i <= n; i ++ ) {
            int w;
            scanf ( "%d", &w );
            add ( i + n, t, w );
        }
        for ( int i = 1; i <= n; i ++ ) {
            int w;
            scanf ( "%d", &w );
            add ( s, i, w );
        }
        for ( int i = 1; i <= m; i ++ ) {
            int u, v;
            scanf ( "%d%d", &u, &v );
            add ( u, v + n, inf );
        }
        int ans = 0;
        while ( bfs ( ) ) {
            for ( int i = s; i <= t; i ++ )
                hh[i] = h[i];
            ans += dfs ( s, inf );
        }
        printf ( "%d", ans );
        return 0;
    }
  • 相关阅读:
    深入理解Java Proxy机制
    StringBuilder与StringBuffer的区别
    反射
    list和set区别
    spring总结
    Hibernate与 MyBatis的比较
    手机拍照或选择照片上传html5代码
    JSP两种跳转
    离散化
    圆方树
  • 原文地址:https://www.cnblogs.com/wans-caesar-02111007/p/9492616.html
Copyright © 2011-2022 走看看