ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Acwing 4339 敌兵布阵

2022-03-20 11:31:49  阅读:153  来源: 互联网

标签:10 ch 4339 int void read inline 布阵 Acwing


来一篇超全题解

数据结构大杂烩

原题连接

题目描述

敌人有 NNN 个工兵营地,编号 1N1∼N1∼N。

初始时,第 iii 个营地有 aia_iai​ 个人。

接下来有若干个命令,命令有 444 种形式:

Add i jiii 和 jjj 为正整数,表示第 iii 个营地增加 jjj 个人。(jjj 不超过 303030)
Sub i jiii 和 jjj 为正整数,表示第 iii 个营地减少 jjj 个人。(jjj 不超过 303030)
Query i jiii 和 jjj 为正整数ij(i≤j)(i≤j),表示询问第 iii 到第 jjj 个营地的总人数。
End,表示结束,此命令只会作为最后一条命令出现。
请你计算每个 Query 的答案。

输入格式
第一行包含整数 TTT,表示共有 TTT 组测试数据。

每组数据第一行包含一个整数 NNN。

第二行包含 NNN 个整数 a1,a2,,aNa1,a2,…,aNa1,a2,…,aN。

接下来若干行,每行包含一条命令,格式如题目所述。

输出格式
对于第 iii 组数据,首先输出一行 Case i:,然后对于每个 Query 询问,输出一行一个整数,表示询问的段中的总人数。

数据范围

1T10,1≤T≤10,1≤T≤10,
1N50000,1≤N≤50000,1≤N≤50000,
1ai50,1≤ai≤50,1≤ai≤50,
每组数据最多有 400004000040000 条命令,
保证任何营地的人数都不会减少为负数。

输入样例:

1
10
1 2 3 4 5 6 7 8 9 10
Query 1 3
Add 3 6
Query 2 7
Sub 10 2
Add 6 3
Query 3 10
End

输出样例:

Case 1:
6
33
59

Code

暴力 + 快读快写 + 吸氧 TL90ptsTL 90ptsTL90pts

#include <cstdio>

#pragma GCC target ("avx") 
#pragma GCC optimize (2, 3, "Ofast", "inline", "-ffast-math")

const int N = 5e4 + 10;

int n, a[N];

namespace IO
{
    template <class T> inline void read (T &x) { x = 0; bool f = 0; char ch = getchar (); while (ch < '0' || ch > '9') f |= ch == '-', ch = getchar (); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar (); x = f ? ~x + 1 : x; }
    template <class T> inline void write (T x) { static char c[20]; unsigned p = 0; if (x < 0) putchar ('-'), x = ~x + 1; if (!x) { putchar ('0'); return ; } while (x) c[++p] = x % 10 ^ 48, x /= 10; while (p) putchar (c[p]), --p; }
    template <class T, class... U> inline void read (T &x, U &...t) { read (x), read (t...); }
    template <class T, class... U> inline void write (T x, U ...t) { write (x), write (t...); }
}

using namespace IO;

int main ()
{
    int _; read (_);
    for (int T = 1; T <= _; ++T)
    {
        read (n);
        for (int i = 1; i <= n; ++i) read (a[i]);
        
        printf ("Case %d:\n", T);
        while (true)
        {
            char opt[5];
            int x, y;
            
            scanf ("%s", opt);
            if (*opt == 'A') read (x, y), a[x] += y;
            if (*opt == 'S') read (x, y), a[x] -= y;
            if (*opt == 'Q')
            {
                read (x, y);
                int res = 0;
                for (int i = x; i <= y; ++i) res += a[i];
                write (res), putchar ('\n');
            }
            if (*opt == 'E') break;
        }
    }
    return 0;
}

优雅的暴力永不过时~~

分块 ACACAC 1194ms1194ms1194ms

O(mn)O(m \sqrt{n})O(mn​)

#include <cstdio>
#include <cmath>
#include <cstring>

#pragma GCC target ("avx")
#pragma GCC optimize (2, 3, "Ofast", "inline", "-ffast-math")

const int N = 5e4 + 10, M = 230;

int n, m, unit, w[N], pos[N], sum[M];

inline void update (int k, int x)
{
    w[k] += x, sum[pos[k]] += x;
}

inline int query (int l, int r)
{
    int res = 0;
    if (pos[l] == pos[r])
        for (int k = l; k <= r; ++k) res += w[k];
    else
    {
        int i = l, j = r;
        while (pos[i] == pos[l]) res += w[i], ++i;
        while (pos[j] == pos[r]) res += w[j], --j;
        for (int k = pos[i]; k <= pos[j]; ++k) res += sum[k];
    }
    return res;
}

namespace IO
{
    template <class T> inline void read (T &x) { x = 0; bool f = 0; char ch = getchar (); while (ch < '0' || ch > '9') f |= ch == '-', ch = getchar (); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar (); x = f ? ~x + 1 : x; }
    template <class T> inline void write (T x) { static char c[20]; unsigned p = 0; if (x < 0) putchar ('-'), x = ~x + 1; if (!x) { putchar ('0'); return ; } while (x) c[++p] = x % 10 ^ 48, x /= 10; while (p) putchar (c[p]), --p; }
    template <class T, class... U> inline void read (T &x, U &...t) { read (x), read (t...); }
    template <class T, class... U> inline void write (T x, U ...t) { write (x), write (t...); }
}

using namespace IO;

inline void init ()
{
    unit = sqrt (n);
    for (int i = 1; i <= n; ++i) read (w[i]), sum[pos[i] = i / unit] += w[i];
}

int main ()
{
    int _; read (_);
    
    for (int T = 1; T <= _; ++T)
    {
        memset (sum, 0, sizeof sum);
        
        read (n);
        init ();
        
        printf ("Case %d:\n", T);
        while (true)
        {
            char opt[5];
            int x, y;
            scanf ("%s", opt);
            
            if (*opt == 'A') read (x, y), update (x, y);
            if (*opt == 'S') read (x, y), update (x, -y);
            if (*opt == 'Q') read (x, y), write (query (x, y)), putchar ('\n');
            if (*opt == 'E') break;
        }
    }
    return 0;
}

大杀器

线段树 ACACAC 1868ms1868ms1868ms

O(mlog2n)O(m \log_2{n})O(mlog2​n)

#include <cstdio>

#pragma GCC target ("avx")
#pragma GCC optimize (2, 3, "Ofast", "inline", "-ffast-math")

const int N = 5e4 + 10;

int n, a[N], tr[N << 2], tag[N << 2];

inline void push_up (int x)
{
    tr[x] = tr[x << 1] + tr[x << 1 | 1];   
}

inline void push_down (int mid, int l, int r, int x)
{
    tr[x << 1] += tag[x] * (mid - l + 1);
    tr[x << 1 | 1] += tag[x] * (r - mid);
    tag[x << 1] += tag[x], tag[x << 1 | 1] += tag[x], tag[x] = 0;
}

inline void build (int l = 1, int r = n, int x = 1)
{
    if (l == r) tr[x] = a[l];
    else
    {
        int mid = l + r >> 1;
        build (l, mid, x << 1), build (mid + 1, r, x << 1 | 1);
        push_up (x);
    }
}

inline void update (int l, int r, int d, int nl = 1, int nr = n, int x = 1)
{
    if (l > nr || r < nl) return ;
    if (l <= nl && r >= nr) tag[x] += d, tr[x] += d * (nr - nl + 1);
    else
    {
        int mid = nl + nr >> 1;
        push_down (mid, nl, nr, x);
        update (l, r, d, nl, mid, x << 1), update (l, r, d, mid + 1, nr, x << 1 | 1);
        push_up (x);
    }
}

inline int query (int l, int r, int nl = 1, int nr = n, int x = 1)
{
    if (l > nr || r < nl) return 0;
    if (l <= nl && r >= nr) return tr[x];
    else
    {
        int mid = nl + nr >> 1;
        push_down (mid, nl, nr, x);
        return query (l, r, nl, mid, x << 1) + query (l, r, mid + 1, nr, x << 1 | 1);
    }
}

namespace IO
{
    template <class T> inline void read (T &x) { x = 0; bool f = 0; char ch = getchar (); while (ch < '0' || ch > '9') f |= ch == '-', ch = getchar (); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar (); x = f ? ~x + 1 : x; }
    template <class T> inline void write (T x) { static char c[20]; unsigned p = 0; if (x < 0) putchar ('-'), x = ~x + 1; if (!x) { putchar ('0'); return ; } while (x) c[++p] = x % 10 ^ 48, x /= 10; while (p) putchar (c[p]), --p; }
    template <class T, class... U> inline void read (T &x, U &...t) { read (x), read (t...); }
    template <class T, class... U> inline void write (T x, U ...t) { write (x), write (t...); }
}

using namespace IO;

int main ()
{
    int _; read (_);
    
    for (int T = 1; T <= _; ++T)
    {
        read (n);
        for (int i = 1; i <= n; ++i) read (a[i]);
        
        build ();
        printf ("Case %d:\n", T);
        while (true)
        {
            char opt[5];
            int x, y;
            scanf ("%s", opt);
            
            if (*opt == 'A') read (x, y), update (x, x, y);
            if (*opt == 'S') read (x, y), update (x, x, -y);
            if (*opt == 'Q') read (x, y), write (query (x, y)), putchar ('\n');
            if (*opt == 'E') break;
        }
    }
    return 0;
}

常数稍小的线段树

ZkwZkwZkw线段树 ACACAC 1158ms1158ms1158ms

O(mlog2n)O(m \log_2{n})O(mlog2​n)

#include <cstdio>
#include <cstring>

#pragma GCC target ("avx")
#pragma GCC optimize (2, 3, "Ofast", "inline", "-ffast-math")

const int N = 5e4 + 10;

int n, M, a[N], tr[N << 2], tag[N << 2];

inline void update (int s, int t, int d)
{
    int ln = 0, rn = 0, nn = 1;
    for (s += M - 1, t += M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nn <<= 1)
    {
        tr[s] += d * ln, tr[t] += d * rn;
        if (~s & 1) tag[s ^ 1] += d, tr[s ^ 1] += d * nn, ln += nn;
        if (t & 1) tag[t ^ 1] += d, tr[t ^ 1] += d * nn, rn += nn;
    }
    for (; s; s >>= 1, t >>= 1) tr[s] += d * ln, tr[t] += d * rn;
}

inline int query (int s, int t)
{
    int ans = 0, ln = 0, rn = 0, nn = 1;
    for (s += M - 1, t += M + 1; s ^ t ^ 1; s >>= 1, t >>= 1, nn <<= 1)
    {
        if (tag[s]) ans += tag[s] * ln;
        if (tag[t]) ans += tag[t] * rn;
        if (~s & 1) ans += tr[s ^ 1], ln += nn;
        if (t & 1) ans += tr[t ^ 1], rn += nn;
    }
    for (; s; s >>= 1, t >>= 1) ans += tag[s] * ln, ans += tag[t] * rn;
    return ans;
}

namespace IO
{
    template <class T> inline void read (T &x) { x = 0; bool f = 0; char ch = getchar (); while (ch < '0' || ch > '9') f |= ch == '-', ch = getchar (); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar (); x = f ? ~x + 1 : x; }
    template <class T> inline void write (T x) { static char c[20]; unsigned p = 0; if (x < 0) putchar ('-'), x = ~x + 1; if (!x) { putchar ('0'); return ; } while (x) c[++p] = x % 10 ^ 48, x /= 10; while (p) putchar (c[p]), --p; }
    template <class T, class... U> inline void read (T &x, U &...t) { read (x), read (t...); }
    template <class T, class... U> inline void write (T x, U ...t) { write (x), write (t...); }
}

using namespace IO;

inline void init ()
{
    M = 1;
    while (M <= n + 1) M <<= 1;
    for (int i = 1; i <= n; ++i) read (tr[M + i]);
    for (int i = M - 1; i; --i) tr[i] = tr[i << 1] + tr[i << 1 | 1];
}

int main ()
{
    int _; read (_);
    
    for (int T = 1; T <= _; ++T)
    {
        read (n);
        init ();
        
        printf ("Case %d:\n", T);
        while (true)
        {
            char opt[5];
            int x, y;
            
            scanf ("%s", opt);
            if (*opt == 'A') read (x, y), update (x, x, y);
            if (*opt == 'S') read (x, y), update (x, x, -y);
            if (*opt == 'Q') read (x, y), write (query (x, y)), putchar ('\n');
            if (*opt == 'E') break;
        }
    }
    return 0;
}

树状数组 ACACAC 890ms890ms890ms

O(mlog2n)O(m \log_2{n})O(mlog2​n)

#include <cstdio>
#include <cstring>

#pragma GCC target ("avx")
#pragma GCC optimize (2, 3, "Ofast", "inline", "-ffast-math")

#define lowbit(x) ((x) & ~(x) + 1)

const int N = 5e4 + 10;

int n, tr[N];

inline void update (int k, int x)
{
    while (k <= n) tr[k] += x, k += lowbit (k);
}

inline int query (int k)
{
    int ans = 0;
    while (k) ans += tr[k], k -= lowbit (k);
    return ans;
}

namespace IO
{
    template <class T> inline void read (T &x) { x = 0; bool f = 0; char ch = getchar (); while (ch < '0' || ch > '9') f |= ch == '-', ch = getchar (); while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + (ch ^ 48), ch = getchar (); x = f ? ~x + 1 : x; }
    template <class T> inline void write (T x) { static char c[20]; unsigned p = 0; if (x < 0) putchar ('-'), x = ~x + 1; if (!x) { putchar ('0'); return ; } while (x) c[++p] = x % 10 ^ 48, x /= 10; while (p) putchar (c[p]), --p; }
    template <class T, class... U> inline void read (T &x, U &...t) { read (x), read (t...); }
    template <class T, class... U> inline void write (T x, U ...t) { write (x), write (t...); }
}

using namespace IO;

int main ()
{
    int _; read (_);
    
    for (int T = 1; T <= _; ++T)
    {
        memset (tr, 0, sizeof tr);
        
        read (n);
        for (int i = 1, x; i <= n; ++i)
        {
            read (x), tr[i] += x;
            if (i + lowbit (i) <= n) tr[i + lowbit (i)] += tr[i];
        }
        
        printf ("Case %d:\n", T);
        while (true)
        {
            char opt[5];
            int x, y;
            scanf ("%s", opt);
            
            if (*opt == 'A') read (x, y), update (x, y);
            if (*opt == 'S') read (x, y), update (x, -y);
            if (*opt == 'Q') read (x, y), write (query (y) - query (x - 1)), putchar ('\n');
            if (*opt == 'E') break;
        }
    }
    return 0;
}

总结:

想题目中这样的数据范围,暴力一般都是过不了的,我们自然而然地就想到了上述的这些O(mn)O(m\sqrt{n})O(mn​)和O(mlog2n)O(m\log_2{n})O(mlog2​n)的数据结构。只要把模板打熟,以后遇到这样的题就不怕了~~

制作不易,请一键三连~~

标签:10,ch,4339,int,void,read,inline,布阵,Acwing
来源: https://blog.csdn.net/WangXinyu_090926/article/details/123609808

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有