zoukankan      html  css  js  c++  java
  • 0118ACM自闭赛

    <前言>

    ACM赛:vjudge 20200118acm赛

    好好记录一下自己干了啥。

    就是在颓废。

    <正文>

    <考试经历>

    今天acm赛队友随便找了个,结果就是个懒货,题都不写几道,哎。

    他写了一道最水的E,然后两道是我写的,我挺想骂人。

    这次的题简直毒瘤,无法描述。

    比赛地址

    密码:nicaibudao


    上场我先说队友(zjh)分配一下题。他就直接捡了个E题,几分钟爆切,全场一血,我当时吓死了,然而考试后得知E题最水,代码就几行。

    我拿到了D题,稍微看了下,做过原题或是一样的题,几分钟也写完了,却不是一血。区间最小值和不就是维护一个单调栈然后瞎搞就行了。来回各一趟维护出数组,再直接计算。

    接着全场陷入瓶颈期,很长时间没人切出除了DE外的题。

    然后先不管fjz的吊打全场,我开始磕F题,队友写完E之后就开始无(da)所(shui)事(te)事(shui),他们都去吃饭了,我在机房磕。

    一直在6点WA,不知为何。万念俱灰间加了个long long 他还就真过了。。(掀桌)

    然后时间就是各题看看,也磕不出来惹。。。自闭

    最后只有rank5,没泡面,但是我两顿没吃了啊啊啊啊啊啊啊啊啊啊啊啊啊啊。

    晚上,也就是现在,开始四处觅食,感觉都没吃的,就自闭写blog去了。

    游戏体验极差,全程被吊打。也就一开始的时候成为了好久的rank1,因为大家都做不出来。

    贴一张骄傲的图(PS:号是队友的,取名雨我无瓜):


    部分题解

    A - Negative Cycle AtCoder - 5147

    A题不会,抄了一下,至少自己写不出来,看着还好理解的样子。

    (mathrm{Code:})

    #include <bits/stdc++.h>
    #define N      510
    #define int    long long
    using namespace std;
    int a[N][N] = {};
    int read()
    {
        int  s = 0, w = 1;
        char c = getchar();
        while ((c < '0' || c > '9') && c != '-')
            c = getchar();
        if (c == '-')
            c = getchar(), w = -1;
        while (c <= '9' && c >= '0')
            s = (s << 3) + (s << 1) + c - '0', c = getchar();
        return s * w;
    }
    int n;
    int b[N][N] = {}, c[N][N] = {};
    int f[N][N] = {};
    signed main()
    {
        n = read();
        for (int i = 1; i <= n; ++i)
            for (int j = 1; j <= n; ++j)
                if (i != j)
                    a[i][j] = read();
        for (int i = 1; i <= n; ++i)
            for (int j = n; j >= i + 1; --j)
            {
                b[i][j] = b[i][j + 1];
                for (int k = 1; k <= i; ++k)
                    b[i][j] += a[j][k];
            }
        for (int i = 1; i <= n; ++i)
            for (int j = i + 1; j <= n + 1; ++j)
            {
                c[i][j] = c[i][j - 1];
                for (int k = i; k <= j - 1; ++k)
                    c[i][j] += a[k][j];
            }
        memset(f, 0x3f, sizeof(f));
        f[0][0] = 0;
        for (int i = 0; i <= n; ++i)
            for (int j = i; j <= n; ++j)
                if (f[i][j] < 1e18)
                    for (int k = j + 1; k <= n + 1; ++k)
                        f[j][k] = min(f[j][k], f[i][j] + c[j + 1][k] + b[j][k + 1] - b[i][k + 1]);
        int minn = 1e18;
        for (int i = 0; i <= n; ++i)
            minn = min(minn, f[i][n + 1]);
        printf("%lld
    ", minn);
        return 0;
    }
    
    

    B - Robots and Exits - AtCoder - 4353

    B题干脆不写了,刷题记录表里随便写点就行了。

    C - 和風いろはちゃん / Iroha and Haiku - AtCoder - 1975

    C题同。

    D - Minimum Sum - AtCoder - 2060

    稍微讲一下D,这题就是求每段子区间的最小值和。

    每段考虑并不好做,考虑计算每个值的贡献。

    一个位于(i)处的值(x)能影响到的区间一定是以它为最小值的区间,我们只需找到左右第一个比它小的值位置,这两个位置之间的区间都是以(x)为最小值得区间,计算个数以及贡献即可。

    [egin{aligned} & sum_{1leq l leq r leq n} min(a_l,a_{l+1}……a_{r-1},a_r)\ &= sum_{min(a_l,a_{l+1}……a_{r-1},a_r)=x} (r-i+1) imes (i-l+1) imes x end{aligned} ]

    两个单调栈一开,维护左/右比x小的第一个数位置,就分别是l、r了。

    (mathrm{Code:})

    #include <bits/stdc++.h>
    #define N      200010
    #define int    long long
    using namespace std;
    int n;
    int a[N] = {};
    int read()
    {
        int  s = 0, w = 1;
        char c = getchar();
        while ((c < '0' || c > '9') && c != '-')
            c = getchar();
        if (c == '-')
            w = -1, c = getchar();
        while (c <= '9' && c >= '0')
            s = (s << 3) + (s << 1) + c - '0', c = getchar();
        return s * w;
    }
    int pre[N] = {}, suf[N] = {};
    int q[N << 1] = {}, h = 1, t = 0;
    void push1(int x)
    {
        while (h <= t && a[q[t]] >= a[x])
            suf[q[t]] = x - 1, --t;
        q[++t] = x;
    }
    void push2(int x)
    {
        while (h <= t && a[q[t]] >= a[x])
            pre[q[t]] = x + 1, --t;
        q[++t] = x;
    }
    signed main()
    {
        n = read();
        for (int i = 1; i <= n; ++i)
            a[i] = read(), pre[i] = 1, suf[i] = n;
        for (int i = 1; i <= n; ++i)
            push1(i);
        h = 1; t = 0;
        for (int i = n; i >= 1; --i)
            push2(i);
        int sum = 0;
        for (int i = 1; i <= n; ++i)
        {
            sum += (i - pre[i] + 1) * (suf[i] - i + 1) * a[i];
        }
        printf("%lld
    ", sum);
        return 0;
    }
    

    挺水一题,不知为何被拖了很久,没拿到一血。

    E - STring - AtCoder - 2059

    题目给一个巨tm大的操作次数((10^{10000}))就是告诉你随便删就好了,管够。

    所以E作为本场最水被过了。

    zjh的(mathrm{Code:})

    #include <bits/stdc++.h>
    using namespace std ;
    inline int read ()
    {
        char c = getchar () ; int x = 0 , f = 1 ;
        while (c < '0' || c > '9') { if (c == '-') f = -1 ; c = getchar () ; }
        while (c >= '0' && c <= '9'){ x = x * 10 + c - '0' ; c = getchar () ; }
        return x * f ;
    }
    string s ;
    int st[200005] , ans , top ;
    int main ()
    {
    	cin >> s ;
    	ans = s.size () ;
    	for (int i = 0 ; i < s.size () ; i ++)
    	{
    		if (s[i] == 'S') st[++ top] = 'S' ;
    		else if (top) top -- , ans -= 2 ;
    	}
    	cout << ans ;
    }
    

    F - Pizza Delivery - Gym - 101986F

    这题也是我写的。

    一直被long long 卡,要是开了long long 我午饭时间后的第二发就可以A,能吃上一顿饭呢。(但是晚上吃到泡面还是挺赚的)

    之前我的分类讨论中,一开始我就分了最短路边和非最短路边,两者又进行了细分,后来发现不必要,对于非最短路边,直接判断就好。

    最短路边略麻烦。

    你要确定删去之后会不会对最短路径有影响,就要判断该边是否是属于最短路的边(注意最短路可能有多条)组成的图的割边了。

    若不是桥,说明会有其他路径代替本路径,取反这条边没啥卵用。

    若是桥,则它取反之后无法找到更短或相等的路径代替,是可以证明的,但是我不会。

    那么局势变得明朗起来:

    • 找最短路,标记所有最短路上的边。
    • 在最短路径组成的图中找割边,可用两种方式实现。

    对于最短路边,若是割边则翻转会产生影响。不是割边则不会。

    对于非最短路边,强行把它放在最短路上看看和原最短路比起来怎么样。

    割边的两种查找方式:重新建图tarjan,最短路路径计数。

    贴出计数法判割边的代码:

    (mathrm{Code:})

    #include <bits/stdc++.h>
    #define N      200010
    #define int    long long
    #define inf    0x3f3f3f3f
    #define mp(x, y)    make_pair(x, y)
    using namespace std;
    int n, m;
    struct gragh
    {
        int to[N] = {}, net[N] = {}, w[N] = {};
        int from[N] = {};
        int fl[N] = {}, len = 0;
        inline void inc(int x, int y, int z)
        {
            to[++len] = y;
            from[len] = x;
            w[len]    = z;
            net[len]  = fl[x];
            fl[x]     = len;
        }
    } G[2];
    struct tree
    {
        int to[N << 1] = {}, net[N] = {}, w[N] = {};
        int fl[N] = {}, len = 0;
        inline void inc(int x, int y, int z)
        {
            to[++len] = y;
            w[len]    = z;
            net[len]  = fl[x];
            fl[x]     = len;
        }
    } T;
    int read()
    {
        int  s = 0, w = 1;
        char c = getchar();
        while ((c < '0' || c > '9') && c != '-')
            c = getchar();
        if (c == '-')
            c = getchar(), w = -1;
        while (c <= '9' && c >= '0')
            s = (s << 3) + (s << 1) + c - '0', c = getchar();
        return s * w;
    }
    int vis[N] = {}, dis[2][N] = {};
    int is[2][N] = {}, si[2][N] = {};
    void DJ(int st, int p)
    {
        memset(dis[p], 0x3f, sizeof(dis[p]));
        memset(vis, 0, sizeof(vis));
        memset(is[p], 0, sizeof(is[p]));
        dis[p][st] = 0;
        si[p][st]  = 1;
        priority_queue<pair<int, int> >q;
        q.push(mp(0, st));
        while (!q.empty())
        {
            int t = q.top().second;
            q.pop();
            if (vis[t])
                continue;
            vis[t] = 1;
            for (int i = G[p].fl[t]; i; i = G[p].net[i])
            {
                int v = G[p].to[i];
                if (dis[p][v] > dis[p][t] + G[p].w[i])
                {
                    dis[p][v] = dis[p][t] + G[p].w[i];
                    si[p][v]  = si[p][t];
                    q.push(mp(-dis[p][v], v));
                }
                else if (dis[p][v] == dis[p][t] + G[p].w[i])
                    si[p][v] += si[p][t], si[p][v] %= inf;
            }
        }
    }
    signed main()
    {
        n = read();
        m = read();
        for (int i = 1; i <= m; ++i)
        {
            int x = read(), y = read(), z = read();
            G[0].inc(x, y, z);
            G[1].inc(y, x, z);
        }
        DJ(1, 0);
        DJ(2, 1);
        int vis[N] = {};
        for (int i = 1; i <= G[0].len; ++i)
            if (dis[0][G[0].from[i]] + G[0].w[i] + dis[1][G[0].to[i]] == dis[0][2])
                is[0][i] = 1, 
                vis[G[0].from[i]] = vis[G[0].to[i]] = 1;
        for (int i = 1; i <= G[0].len; ++i)
        {
            if (is[0][i])
            {
                int u = G[0].from[i], v = G[0].to[i];
                if (si[0][u] * si[1][v] % inf == si[0][2])
                {
                    puts("SAD");
                }
                else
                {
                    puts("SOSO");
                }
            }
            else
            {
                int u = G[0].from[i], v = G[0].to[i];
                int minn = dis[0][v] + G[0].w[i] + dis[1][u];
                if (minn < dis[0][2])
                    puts("HAPPY");
                else
                    puts("SOSO");
            }
        }
        return 0;
    }
    

    G - New Year and Old Subsequence - CodeForces - 750E

    本题已经被归类了,详见这里

    H - Shorten Diameter - AtCoder - 1981

    没搞,听说第二水,也不想写了。

    <后记>

    然后就是这样了,一场ACM打完,神清气爽,回头刷题。

  • 相关阅读:
    有序数组(类模板)
    BUUCTF-Web Comment
    BUUCTF-web NiZhuanSiWei
    2020数字中国创新大赛虎符网络安全赛道-pwn count
    BUUCTF-Web Easy Calc
    xctf-web fakebook
    xctf-web supersqli
    xctf-pwn pwn200
    xctf-pwn level3
    利用updatexml()报错注入mysql
  • 原文地址:https://www.cnblogs.com/yywxdgy/p/12210945.html
Copyright © 2011-2022 走看看