• NEU_Train_Camp_2020_基础数据结构



    title: NEU_Train_Camp_2020_基础数据结构
    date: 2020-07-13 21:13:03
    tags:

    • c++
      categories:
    • New
      cover:

    基础数据结构

    A - Web Navigation

    POJ-1028

    #include <string>
    #include <iostream>
    #include <stack>
    
    using namespace std;
    
    void clear(stack<string> &a)
    {
        while (!a.empty())
            a.pop();
    }
    
    int main(void)
    {
        stack<string> forw, bac;
        string cur = "http://www.acm.org/";
        string oper;
        while (cin >> oper and oper != "QUIT")
        {
            if (oper == "VISIT")
            {
                clear(forw);
                bac.push(cur);
                cin >> cur;
                cout << cur << endl;
            }
            else if (oper == "BACK")
            {
                if (bac.empty())
                    cout << "Ignored" << endl;
                else
                {
                    forw.push(cur);
                    cur = bac.top();
                    bac.pop();
                    cout << cur << endl;
                }
            }
            else
            {
                //FORWARD
                if (forw.empty())
                    cout << "Ignored" << endl;
                else
                {
                    bac.push(cur);
                    cur = forw.top();
                    forw.pop();
                    cout << cur << endl;
                }
            }
        }
        return 0;
    }
    

    B - 简单计算器

    HDU 1237

    我吐了我吐了我吐了,wa了一上午,我吐了我吐了我吐了

    #include <iostream>
    #include <iomanip>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main(void)
    {
        stack<double> num;
        string in;
        while (getline(cin, in))
        {
            char op = '!';
            if (in.size() == 1 && in[0] == '0')
                break;
            for (size_t i = 0; i < in.size(); i++)
            {
                if (in[i] == ' ')
                    continue;
                if (isdigit(in[i]))
                {
                    double n = in[i] - '0';
                    for (size_t j = i + 1; j < in.size(); j++)
                    {
                        if (isdigit(in[j]))
                        {
                            n = n * 10 + in[j] - '0';
                            i = j + 1;
                        }
                        else
                            break;
                    }
                    if (op == '!')
                        num.push(n * 1.0);
                    else
                    {
                        double t;
                        switch (op)
                        {
                        case '+':
                            num.push(n);
                            break;
                        case '-':
                            num.push(-n);
                            break;
                        case '*':
                            t = num.top();
                            num.pop();
                            num.push(t * n);
                            break;
                        case '/':
                            t = num.top();
                            num.pop();
                            num.push(t / n);
                            break;
                        default:
                            break;
                        }
                        op = '!';
                    }
                }
                else
                {
                    op = in[i];
                }
            }
            double ans = 0;
            while (!num.empty())
            {
                ans += num.top();
                num.pop();
            }
            // cout << fixed << setprecision(2) << ans << endl;  //G++交上去wa , C++ 交上去ac ,vjudge平台
            printf("%.2lf
    ", ans);
        }
        return 0;
    }
    

    C - Catch That Cow

    POJ 3278

    直接bfs,这简单题应该放在第一场第一题(逃)

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    int n, k;
    bool vis[100002];
    
    bool isLegal(pair<int, int> t)
    {
        if (0 <= t.first and t.first <= 100000 and !vis[t.first])
            return true;
        return false;
    }
    
    int bfs(int s)
    {
        queue<pair<int, int> > que;
        que.push(make_pair(s, 0));
        vis[s] = true;
        while (!que.empty())
        {
            pair<int, int> f = que.front();
            que.pop();
            if (f.first == k)
            {
                return f.second;
            }
            pair<int, int> t = f;
            --t.first;
            if (isLegal(t))
            {
                vis[t.first] = true;
                t.second++;
                que.push(t);
            }
            t = f;
            t.first++;
            if (isLegal(t))
            {
                vis[t.first] = true;
                t.second++;
                que.push(t);
            }
            t = f;
            t.first *= 2;
            if (isLegal(t))
            {
                vis[t.first] = true;
                t.second++;
                que.push(t);
            }
        }
        return -1;
    }
    
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        cin >> n >> k;
        cout << bfs(n) << endl;
        return 0;
    }
    

    D - Team Queue

    HDU 1387 && UVa 540

    使用map对队伍进行分组,一个队伍对应一个value ... 当然unordered_map更快,奈何hdu,poj都不支持

    常数时间的插入删除,使用std::list<int> 模拟队列

    vector<list<int>::iterator>存每个队伍,在队列中最后一个成员的位置.

    pop元素是该队伍在队列中的唯一一个元素,要更新该队伍的迭代器为end()
    之前我这里没有注意,re了

    注意:list进行pop后,指向的迭代器会失效 , 所以re了,而不是wa了

    #include <cstdio>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #include <map>
    #include <list>
    using namespace std;
    int main(void)
    {
        list<int> que;
        map<int, int> vis;
        vector<list<int>::iterator> pos;
        int count = 1;
        int t;
        while (scanf("%d", &t))
        {
            if (t == 0)
                break;
            que.clear();
            vis.clear();
            pos.clear();
            pos.resize(t);
            fill(pos.begin(), pos.end(), que.end());
            printf("Scenario #%d
    ", count++);
            for (size_t i = 0; i < t; i++)
            {
                int n;
                scanf("%d", &n);
                for (int j = 0; j < n; j++)
                {
                    int in;
                    scanf("%d", &in);
                    vis[in] = i + 1;
                }
            }
            char op[100];
            while (scanf("%s", op) and op[0] != 'S')
            {
                if (op[0] == 'D')
                {
                    printf("%d
    ", que.front());
                    if (pos[vis[que.front()] - 1] == que.begin()) //这里re了
                        pos[vis[que.front()] - 1] = que.end();
                    que.pop_front();
                }
                else
                {
                    int in;
                    scanf("%d", &in);
                    int temp = vis[in] - 1;
                    list<int>::iterator nowp = pos[temp];
                    if (nowp == que.end())
                        pos[temp] = que.insert(nowp, in);
                    else
                        pos[temp] = que.insert(++nowp, in);
                }
            }
            printf("
    ");
        }
        return 0;
    }
    
    

    不完全总结迭代器失效

    • 序列式容器
      • 内存重新分配时 , 所有的迭代器都将失效
      • 删除当前的iterator会使后面所有元素的iterator都失效
        • insert() erase()
    • 关联式容器
      • 被删除的元素的迭代器失效

    E - Bad Hair Day

    POJ 3250

    单调栈

    最开始两层循环暴力,tle

    看了题解使用了单调栈

    我原来想的是每头牛最多能看见他右边几头牛 , 单调栈代表的思想是每头牛能被他左边最多几头牛看见,一头牛入栈时,栈内元素数量就是能看见他的牛的数量.

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int n;
        cin >> n;
        long long ans(0);
        stack<int> s;
        int h;
        cin >> h;
        s.push(h);
        for (int i = 1; i < n; i++)
        {
            cin >> h;
            while (!s.empty() and s.top() <= h)
            {
                s.pop();
            }
            ans += s.size();
            s.push(h);
        }
        cout << ans;
        return 0;
    }
    

    单调栈经典例题 84.柱状图中最大的矩形

    与上面奶牛那个不太一样

    class Solution
    {
    public:
        int largestRectangleArea(vector<int> &heights)
        {
            vector<pair<int, int>> touch(heights.size());
            stack<int> s;
            for (size_t i = 0; i < heights.size(); i++)
            {
                //入栈时确定左边界,出栈确定右边界
                while (!s.empty() and heights[i] <= heights[s.top()])
                {
                    touch[s.top()].second = i - 1;
                    s.pop();
                }
                touch[i].first = s.empty() ? 0 : s.top() + 1;
                s.push(i);
            }
            while (!s.empty())
            {
                touch[s.top()].second = heights.size() - 1;
                s.pop();
            }
            int tmax = 0;
            for (size_t i = 0; i < touch.size(); i++)
            {
                tmax = max(tmax, (touch[i].second - touch[i].first + 1) * heights[i]);
            }
            return tmax;
        }
    	//另一种写法,不够优雅
        int largestRectangleArea1(vector<int> &heights)
        {
            vector<pair<int, int>> res(heights.size());
            stack<int> s;
            for (int i = 0; i < heights.size(); i++)
            {
                while (!s.empty() and heights[i] <= heights[s.top()])
                    s.pop();
                res[i].first = s.empty() ? -1 : s.top();
                s.push(i);
            }
            while (!s.empty())
            {
                s.pop();
            }
            for (int i = heights.size() - 1; i >= 0; i--)
            {
                while (!s.empty() and heights[i] <= heights[s.top()])
                    s.pop();
                res[i].second = s.empty() ? heights.size() : s.top();
                s.push(i);
            }
            int tmax = 0;
            for (int i = 0; i < res.size(); i++)
            {
                if ((res[i].second - res[i].first - 2 + 1) * heights[i] > tmax)
                    tmax = (res[i].second - res[i].first - 2 + 1) * heights[i];
            }
            return tmax;
        }
    };
    

    F - How Many Tables

    简单的并查集

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    
    using namespace std;
    int n, m;
    int fa[1010];
    
    int findfa(int a)
    {
        if (fa[a] == a)
        {
            return a;
        }
        else
        {
            return fa[a] = findfa(fa[a]);
        }
    }
    
    void unio(int a, int b)
    {
        a = findfa(a);
        b = findfa(b);
        if (a != b)
            fa[b] = a;
    }
    
    void init()
    {
        for (size_t i = 1; i <= n; i++)
        {
            fa[i] = i;
        }
    }
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int t;
        cin >> t;
        while (t--)
        {
            cin >> n >> m;
            init();
            for (int i = 0; i < m; i++)
            {
                int a, b;
                cin >> a >> b;
                unio(a, b);
            }
            int ans(0);
            for (int i = 1; i <= n; i++)
            {
                if (i == fa[i])
                    ans++;
            }
            cout << ans
            << endl;
        }
        return 0;
    }
    

    G - 畅通工程

    HDU 1863

    没思路.

    最小生成树, 挑战程序设计竞赛 p105

    prim+邻接表+优先队列 _没太理解

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #define mp(a, b) make_pair(a, b)
    using namespace std;
    using p = pair<int, int>;
    vector<p> edge[102];
    bool vis[102];
    int n, m;
    
    void prim()
    {
        priority_queue<p, vector<p>, greater<p>> que;
        que.push(mp(0, 1));
        int ans = 0;
        while (!que.empty())
        {
            p u = que.top();
            que.pop();
            if (!vis[u.second])
            {
                vis[u.second] = true;
                ans += u.first;
                for (int i = 0; i < edge[u.second].size(); i++)
                {
                    p v = edge[u.second][i];
                    if (!vis[v.second])
                    {
                        que.push(v);
                    }
                }
            }
        }
        
        //binary_search要求数组有序,故使用find
        if (find(vis + 1, vis + m + 1, false) == vis + m + 1)
            cout << ans << endl;
        else
            cout << '?' << endl;
    }
    
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        while (cin >> n >> m and n != 0)
        {
            for (size_t i = 0; i <= m; i++)
            {
                edge[i].clear();
            }
            memset(vis, 0, sizeof(vis));
            for (size_t i = 0; i < n; i++)
            {
                int a, b, c;
                cin >> a >> b >> c;
                edge[a].push_back(mp(c, b));
                edge[b].push_back(mp(c, a));
            }
            prim();
        }
        return 0;
    }
    

    网上抄的

    #include <cstdio>
    #include <cstdlib>
    #include <iostream>
    #include <stack>
    #include <queue>
    #include <algorithm>
    #include <cstring>
    #include <string>
    #include <vector>
    using namespace std;
    
    #define INF 0x3f3f3f3f
    #define MAXN 120
    typedef long long ll;
    int n, q;
    int V;
    int res;
    int mincost[MAXN];
    int used[MAXN];
    
    struct edge
    {
        int to, cost;
        edge() {}
        edge(int to, int cost) : to(to), cost(cost) {}
    };
    vector<edge> G[MAXN]; //存放从i出发的边
    
    typedef pair<int, int> P; //first存放距离,second存放节点
    priority_queue<P, vector<P>, greater<P>> que;
    
    void prim()
    {
        memset(used, 0, sizeof(used));
        fill(mincost, mincost + V, INF);
        res = 0;
        que.push(P(0, 0));
    
        while (!que.empty())
        {
            P p = que.top();
            que.pop();
            int v = p.second, d = p.first;
            if (used[v])
                continue;
            used[v] = 1;
            res += d;
    
            for (int i = 0; i < G[v].size(); i += 1)
            {
                edge e = G[v][i];
                if ((mincost[e.to] > e.cost) && !used[i])
                {
                    mincost[e.to] = e.cost;
                    que.push(P(mincost[e.to], e.to));
                }
            }
        }
        printf("%d
    ", res);
    }
    
    int main()
    {
        while (scanf("%d", &n) != EOF)
        {
            memset(G, 0, sizeof(G)); //每次要初始化啊
            for (int i = 0; i < n; i += 1)
            {
                for (int j = 0; j < n; j += 1)
                {
                    int a;
                    cin >> a;
                    G[i].push_back(edge(j, a));
                }
            }
            cin >> q;
            for (int i = 0; i < q; i += 1)
            {
                int a, b;
                cin >> a >> b;
                G[a - 1][b - 1].cost = G[b - 1][a - 1].cost = 0;
            }
            V = n;
            prim();
        }
        return 0;
    }
    

    H - 食物链

    POJ - 1182

    我称之为并查集的进阶

    挑战程序设计竞赛 p88

    POJ - 1182: 食物链 (并查集)

    这种比带权那种解法更容易理解,但显著的缺点就是废空间;

    使用cin会tle

    #include <cstdio>
    #include <iostream>
    using namespace std;
    int n, k;
    int fa[150014];
    void init()
    {
        for (int i = 1; i <= 3 * n; i++)
        {
            fa[i] = i;
        }
    }
    
    int findfa(int a)
    {
        if (fa[a] == a)
            return a;
        else
            return fa[a] = findfa(fa[a]);
    }
    
    void unio(int a, int b)
    {
        a = findfa(a);
        b = findfa(b);
        if (a != b)
            fa[a] = b;
    }
    
    bool judge(int a, int b)
    {
        return findfa(a) == findfa(b);
    }
    
    int main(void)
    {
        ios::sync_with_stdio(0);
        cin.tie(0);
        cout.tie(0);
        // cin >> n >> k;
        scanf("%d %d", &n, &k);
        int ans = 0;
        init();
        while (k--)
        {
            int d, x, y;
            scanf("%d %d %d", &d, &x, &y);
            // cin >> d >> x >> y;  // tle
            if (x > n || y > n || (d == 2 && x == y))
                ans++;
            else
            {
                //若D=1,则表示X和Y是同类。
                if (d == 1)
                {
                    if (judge(x, y + n) || judge(y, x + n)) //判断是否为同类,不是直接去判断,而是没有吃与被吃的关系就是同类
                        ans++;
                    else
                    {
                        unio(x, y);
                        unio(x + n, y + n);
                        unio(x + 2 * n, y + 2 * n);
                    }
                }
                else
                { //若D=2,则表示X吃Y。
                    if (judge(x, y) || judge(y, x + n)) //x,y是同类 或者y吃x
                        ans++;
                    else
                    {
                        unio(x, y + n);
                        unio(x + n, y + 2 * n);
                        unio(x + 2 * n, y);
                    }
                }
            }
        }
        printf("%d
    ", ans);
        // cout << ans << endl;
        return 0;
    }
    

    带权并查集

    https://blog.csdn.net/Cfreezhan/article/details/8767413

    https://zhuanlan.zhihu.com/p/104581351

    我???

    #include <cstdio>
    const int MAX = 50005;
    
    int parent[MAX];
    int rank[MAX];
    
    void MakeSet(int x)
    {
        parent[x] = x;
        rank[x] = 0;
    }
    
    //查找x的集合,回溯时压缩路径,并修改x与father[x]的关系
    int FindSet(int x)
    {
        if (x == parent[x])
            return x;
        else
        {
            //rank[x] = (rank[x] + rank[parent[x]]) % 3; // !!!这么写会wa
            //return parent[x] = FindSet(parent[x]);  //wa
            int t = parent[x];
            parent[x] = FindSet(parent[x]);
            rank[x] = (rank[x] + rank[t]) % 3;
            return parent[x]; // 这样就ac了
        }
    }
    
    //合并x,y所在的集合
    void Union(int x, int y, int d)
    {
        int xRoot = FindSet(x);
        int yRoot = FindSet(y);
        //将集合x所在合并到y所在集合上
        parent[xRoot] = yRoot;
        //更新x的根与x的父节点的关系
        rank[xRoot] = (rank[y] - rank[x] + 3 + d) % 3;
    }
    
    int main()
    {
        int ans = 0;
        int n, k, x, y, d, xRoot, yRoot;
        scanf("%d%d", &n, &k);
        for (int i = 1; i <= n; ++i)
            MakeSet(i);
        while (k--)
        {
            scanf("%d%d%d", &d, &x, &y);
            //如果x或y比n大,或x吃x,是假话
            if (x > n || y > n || (d == 2 && x == y))
            {
                ans++;
            }
            else
            {
                xRoot = FindSet(x);
                yRoot = FindSet(y);
                //如果x,f的父节点相同 ,那么可以判断给出的关系是否正确的
                if (xRoot == yRoot)
                {
                    if ((rank[x] - rank[y] + 3) % 3 != d - 1)
                        ans++;
                }
                else
                {
                    //否则合并x,y
                    Union(x, y, d - 1);
                }
            }
        }
        printf("%d
    ", ans);
        return 0;
    }
    

    I - Snowflake Snow Snowflakes

    POJ 3349

    使用set<vector<int> >会tle,poj又用不了unordered_set

    自建hash表

    了解哈希表概念后,看题解 难度不高

    纯c , 记得用gcc提交 , 用 c 提交会 ce

    事实证明,用纯c不会更快,也不会更小 (逃)

    20200723 2336 48
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    
    struct node
    {
        int a[6];
    };
    
    struct node hash[15000][1000];
    int hashLen[15000];
    
    int getHash(struct node *p)
    {
        long long t = 0;
        int i;
        for (i = 0; i < 6; i++)
        {
            t += p->a[i];
        }
        return (int)(t % 14997);
    }
    
    int cmp(const void *a, const void *b)
    {
        return *(int *)(a) - *(int *)(b);
    }
    
    int isSame(struct node j, struct node k)
    {
        qsort(j.a, 6, sizeof(int), cmp);
        qsort(k.a, 6, sizeof(int), cmp);
        int i;
        for (i = 0; i < 6; i++)
        {
            if (j.a[i] != k.a[i])
                return 0;
        }
        return 1;
    }
    
    int hashInsert(struct node *t)
    {
        int tkey = getHash(t);
        int i;
        for (i = 0; i < hashLen[tkey]; i++)
        {
            if (isSame(*t, hash[tkey][i]))
            {
                return 0;
            }
        }
        hash[tkey][hashLen[tkey]++] = *t;
        return 1;
    }
    
    int main()
    {
        int t;
        scanf("%d", &t);
        struct node tmp;
        int i;
        for (i = 0; i < t; i++)
        {
            int j;
            for (j = 0; j < 6; j++)
            {
                scanf("%d", &tmp.a[j]);
            }
            if (!hashInsert(&tmp))
            {
                printf("Twin snowflakes found.");
                return 0;
            }
        }
        printf("No two snowflakes are alike.
    ");
        return 0;
    }
    

    记录下ce原因

    Main.c
    F:	emp21837784.264775Main.c(34) : error C2143: syntax error : missing ';' before 'type'
    F:	emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(35) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(37) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(37) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(62) : error C2143: syntax error : missing ';' before 'type'
    F:	emp21837784.264775Main.c(63) : error C2143: syntax error : missing ';' before 'type'
    F:	emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(64) : error C2065: 'i' : undeclared identifier
    F:	emp21837784.264775Main.c(69) : error C2065: 'tmp' : undeclared identifier
    F:	emp21837784.264775Main.c(69) : error C2224: left of '.a' must have struct/union type
    F:	emp21837784.264775Main.c(71) : error C2065: 'tmp' : undeclared identifier
    

    poj用的是远古的vc++

    Visual Studio only supports C89. That means that all of your variables must be declared before anything else at the top of a function.

    小改一下,就ac了

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <math.h>
    
    struct node
    {
        int a[6];
    };
    
    struct node hash[15000][1000];
    int hashLen[15000];
    
    int getHash(struct node *p)
    {
        long long t = 0;
        int i;
        for (i = 0; i < 6; i++)
        {
            t += p->a[i];
        }
        return (int)(t % 14997);
    }
    
    int cmp(const void *a, const void *b)
    {
        return *(int *)(a) - *(int *)(b);
    }
    
    int isSame(struct node j, struct node k)
    {
        int i;
        qsort(j.a, 6, sizeof(int), cmp);
        qsort(k.a, 6, sizeof(int), cmp);
        for (i = 0; i < 6; i++)
        {
            if (j.a[i] != k.a[i])
                return 0;
        }
        return 1;
    }
    
    int hashInsert(struct node *t)
    {
        int tkey = getHash(t);
        int i;
        for (i = 0; i < hashLen[tkey]; i++)
        {
            if (isSame(*t, hash[tkey][i]))
            {
                return 0;
            }
        }
        hash[tkey][hashLen[tkey]++] = *t;
        return 1;
    }
    
    int main()
    {
        int t;
        int i;
        int j;
        struct node tmp;
        scanf("%d", &t);
        for (i = 0; i < t; i++)
        {
            for (j = 0; j < 6; j++)
            {
                scanf("%d", &tmp.a[j]);
            }
            if (!hashInsert(&tmp))
            {
                printf("Twin snowflakes found.");
                return 0;
            }
        }
        printf("No two snowflakes are alike.
    ");
        return 0;
    }
    

    J - Power Strings

    最小循环节若存在,则其长度等于len-next[len],证明

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    int Next[1000010];
    using namespace std;
    
    int getNext(string &a)
    {
        Next[0] = -1;
        int i = 0, j = -1;
        while (i < a.length())
        {
            if (j == -1 or a[i] == a[j])
                Next[++i] = ++j;
            else
                j = Next[j];
        }
        return Next[a.length()];
    }
    
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        string a;
        while (cin >> a and a[0] != '.')
        {
            int n = a.length();
            int x = n - getNext(a);
            if (n % x == 0) // 若有解,那么最短循环节长度为 x = n - nex[n] 。
            {
                cout << n / x
                     << endl;
            }
            else
            {
                cout << 1 << endl;
            }
        }
        return 0;
    }
    

    kmp模板

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    int pnext[2000000];
    using namespace std;
    
    void getNext(string &str)
    {
        pnext[0] = -1;
        int j = 0, k = -1;
        while (j < str.length() - 1)
        {
            if (k == -1 or str[j] == str[k])
            {
                pnext[++j] = ++k;
            }
            else
            {
                k = pnext[k];
            }
        }
    }
    
    string kmp(string &s, string &patten)
    {
        int i = 0, j = 0;
        while (i < s.length())
        {
            if (j == -1 or s[i] == patten[j])
            {
                ++i, ++j;
            }
            else
            {
                j = pnext[j];
            }
    
            if (j == patten.length())
            {
                return s.substr(i - j, j);
                // j = pnext[j];    //继续寻找
            } 
        }
        return "";  
    }
    
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        string s = "abbbadabaabcabadba";
        string pattern = "abaabcaba";
        getNext(pattern);
        cout << kmp(s, pattern);
        return 0;
    }
    

    K - A Simple Problem with Integers

    此题删掉了

    L - Sliding Window

    POJ 2823

    单调队列

    OI WIKI单调队列介绍

    c++ ac ,g++ wa ,太诡异了

    题解的代码g++提交上去就ac

    诡异,诡异 , 对数组的随机访问很耗时吗?poj g++的诡异

    #include <vector>
    #include <deque>
    #include <cstdio>
    
    using namespace std;
    vector<int> arr;
    int n, k;
    void slidingMin()
    {
        deque<int> que;
        for (int i = 0; i < k; i++)
        {
            while (!que.empty() && arr[que.back()] >= arr[i])
                que.pop_back();
            que.push_back(i);
        }
        printf("%d", arr[que.front()]);
        for (int i = k; i < n; i++)
        {
            while (!que.empty() && i - que.front() >= k)
                que.pop_front();
            while (!que.empty() && arr[que.back()] >= arr[i])
                que.pop_back();
            que.push_back(i);
            printf(" %d", arr[que.front()]);
        }
        printf("
    ");
    }
    void slidingMax()
    {
        deque<int> que;
        for (size_t i = 0; i < k; i++)
        {
            while (!que.empty() && arr[que.back()] <= arr[i])
                que.pop_back();
            que.push_back(i);
        }
        printf("%d", arr[que.front()]);
        for (size_t i = k; i < n; i++)
        {
            while (!que.empty() && i - que.front() >= k)
                que.pop_front();
            while (!que.empty() && arr[que.back()] <= arr[i])
                que.pop_back();
            que.push_back(i);
            printf(" %d", arr[que.front()]);
        }
    }
    int main(void)
    {
        scanf("%d %d", &n, &k);
        arr.resize(n);
        for (size_t i = 0; i < n; i++)
        {
            scanf("%d", &arr[i]);
        }
        slidingMin();
        slidingMax();
        return 0;
    }
    

    M - Feel Good

    前缀和+单调栈

    https://blog.nowcoder.net/n/7adc5e27098442cda1e6d31677495ed1

    我太**气了 , tle 我明白,scanf and printfcin and cout快 (c++11以上,关闭同步,应该相差不大)

    wa我实在是不明白,再也不用pair

    先放ac版

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #include <cstdlib>
    #include <cstdio>
    using namespace std;
    
    long long in[100100];
    long long sum[100100];
    int l[100100], r[100100];
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int t;
        scanf("%d", &t);
        sum[0] = 0;
        stack<int> s;
        for (int i = 1; i <= t; i++)
        {
            scanf("%d", &in[i]);
            sum[i] = sum[i - 1] + in[i];
        }
        for (int i = 1; i <= t; i++)
        {
            while (!s.empty() && in[i] <= in[s.top()])
            {
                // touch[s.top()].second = i - 1;
                r[s.top()] = i - 1;
                s.pop();
            }
            l[i] = s.empty() ? 1 : s.top() + 1;
            s.push(i);
        }
        while (!s.empty())
        {
            // touch[s.top()].second = t;
            r[s.top()] = t;
            s.pop();
        }
        long long tmax = 0;
        int rl, rr;
        for (int i = 1; i <= t; i++)
        {
            long long res = (in[i]) * (sum[r[i]] - sum[l[i] - 1]);
            if (tmax <= res)
            {
                tmax = res;
                rl = l[i];
                rr = r[i];
            }
        }
        printf("%lld
    ", tmax);
        printf("%d %d
    ", rl, rr);
        return 0;
    }
    
    

    tle版

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #include <cstdlib>
    #include <cstdio>
    #define p pair<int, int>
    using namespace std;
    
    long long in[100100];
    long long sum[100100];
    p touch[100100];
    int l[100100], r[100100];
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int t;
        cin >> t;
        sum[0] = 0;
        stack<int> s;
        for (int i = 1; i <= t; i++)
        {
            cin >> in[i];
            sum[i] = sum[i - 1] + in[i];
        }
        for (int i = 1; i <= t; i++)
        {
            while (!s.empty() && in[i] <= in[s.top()])
            {
                // touch[s.top()].second = i - 1;
                r[s.top()] = i - 1;
                s.pop();
            }
            l[i] = s.empty() ? 1 : s.top() + 1;
            s.push(i);
        }
        while (!s.empty())
        {
            // touch[s.top()].second = t;
            r[s.top()] = t;
            s.pop();
        }
        long long tmax = 0;
        int rl, rr;
        for (int i = 1; i <= t; i++)
        {
            long long res = (in[i]) * (sum[r[i]] - sum[l[i] - 1]);
            if (tmax <= res)
            {
                tmax = res;
                rl = l[i];
                rr = r[i];
            }
        }
        printf("%lld
    ", tmax);
        printf("%d %d
    ", rl, rr);
        return 0;
    }
    

    wa版

    #include <iostream>
    #include <string>
    #include <cstring>
    #include <queue>
    #include <stack>
    #include <vector>
    #include <algorithm>
    #include <cstdlib>
    #include <cstdio>
    #define p pair<int, int>
    using namespace std;
    
    long long in[100100];
    long long sum[100100];
    int main(void)
    {
        std::ios::sync_with_stdio(false);
        std::cin.tie(0);
        std::cout.tie(0);
        int t;
        cin >> t;
        vector<p> touch(t + 1);
        sum[0] = 0;
        stack<int> s;
        for (int i = 1; i <= t; i++)
        {
            cin >> in[i];
            sum[i] = sum[i - 1] + in[i];
        }
        for (int i = 1; i <= t; i++)
        {
            while (!s.empty() && in[i] <= in[s.top()])
            {
                touch[s.top()].second = i - 1;
                s.pop();
            }
            touch[i].first = s.empty() ? 1 : s.top() + 1;
            s.push(i);
        }
        while (!s.empty())
        {
            touch[s.top()].second = t;
            s.pop();
        }
        long long tmax = 0, l, r;
        for (int i = 1; i <= t; i++)
        {
            long long res = (in[i]) * (sum[touch[i].second] - sum[touch[i].first - 1]);
            if (tmax <= res)
            {
                tmax = res;
                l = touch[i].first;
                r = touch[i].second;
            }
        }
        printf("%I64d
    ", tmax);
        printf("%d %d
    ", l, r);
        return 0;
    }
    
  • 相关阅读:
    【Web-Components】document.registerElement
    Date
    类型转换
    【Web-Components】HTML imports
    【Web-Components】
    【Web-Components】Shadow Dom
    【Mobile】
    数据库读写分离
    HDU——T 1711 Number Sequence
    洛谷——P2957 [USACO09OCT]谷仓里的回声Barn Echoes
  • 原文地址:https://www.cnblogs.com/Delta2019/p/13369664.html
Copyright © 2020-2023  润新知