• 模板


    https://nanti.jisuanke.com/t/41356

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    namespace FastIO {
    #define BUF_SIZE 1000000
        bool IOError = 0;
        inline char NextChar() {
            static char buf[BUF_SIZE], *pl = buf + BUF_SIZE, *pr = buf + BUF_SIZE;
            if(pl == pr) {
                pl = buf, pr = buf + fread(buf, 1, BUF_SIZE, stdin);
                if(pr == pl) {
                    IOError = 1;
                    return -1;
                }
            }
            return *pl++;
        }
    #undef BUF_SIZE
    
        inline bool Blank(char c) {
            return c == ' ' || c == '
    ' || c == '
    ' || c == '	';
        }
    
        template<class T> inline void Read(T &x) {
            char c;
            while(Blank(c = NextChar()));
            if(!IOError) {
                for(x = 0; '0' <= c && c <= '9'; c = NextChar())
                    x = (x << 3) + (x << 1) + c - '0';
            }
        }
    
        template<class T> inline void PutChar(T x) {
            if(x > 9)
                PutChar(x / 10);
            putchar(x % 10 + '0');
        }
    
        template<class T> inline void Write(T &x) {
            PutChar(x);
            putchar('
    ');
        }
    
    }
    
    using namespace FastIO;
    
    const int MAXN = 2e5;
    
    //因为题目的数据有0,所以全部+1偏移了一位
    const int H = 2e5 + 1;
    int bit[H + 5];
    
    inline void clear() {
        memset(bit, 0, sizeof(bit));
    }
    
    inline void add(int x, int v) {
        for(; x <= H; x += x & -x) {
            bit[x] += v;
        }
    }
    
    inline void set0(int x) {
        for(; x <= H; x += x & -x) {
            bit[x] = 0;
        }
    }
    
    inline int sum(int x) {
        int res = 0;
        for(; x ; x -= x & -x) {
            res += bit[x];
        }
        return res;
    }
    
    struct Query {
        int top, x, d1;
        bool operator<(const Query &q)const {
            return x < q.x;
        }
    } q[5 * MAXN + 5], tq[5 * MAXN + 5];
    
    int ans[MAXN + 5];
    bool vis[MAXN + 5];
    
    //超过该界时不进行取消树状数组,直接重建,因为树状数组有很多加法、判断之类的,而memset快得多
    const int BUILDLIMIT = 2e4;
    
    void solve(const int &l, const int &r, bool fl = false) {
        if(l == r)
            return;
        if(!fl) {
            //only update,这个剪枝应该功能强大
            bool ou = true;
            for(int i = l; i <= r ; i++) {
                //发现询问操作,break
                if((q[i].top & 3) >= 2) {
                    ou = false;
                    break;
                }
            }
            if(ou) {
                sort(q + l, q + r + 1);
                return;
            }
        }
        int mid = (l + r) >> 1;
        solve(l, mid);
        solve(mid + 1, r);
    
        int i = l, j = mid + 1, top = 0;
        while(i <= mid || j <= r) {
            if(i > mid || (j <= r && q[j].x < q[i].x)) {
                //把右边的询问加进来
                if((q[j].top & 3) >= 2)
                    tq[++top] = q[j];
                ++j;
            } else {
                //把左边的修改加进来
                if((q[i].top & 3) <= 1)
                    tq[++top] = q[i];
                ++i;
            }
        }
    
        //真正进行的修改操作的次数,用来辅助判断直接重建,可能是负优化
        //int cnt=0;
        for(int i = 1, nxt; i <= top; i = nxt) {
            for(nxt = i + 1; nxt <= top && tq[i].x == tq[nxt].x; ++nxt);
            for(int j = i; j < nxt; ++j) {
                //把修改操作执行
                if((tq[j].top & 3) == 1) {
                    add(tq[j].d1, 1);
                    //++cnt;
                } else if((tq[j].top & 3) == 0) {
                    add(tq[j].d1, -1);
                    //++cnt;
                }
            }
            for(int j = i; j < nxt; ++j) {
                //把询问操作执行
                if((tq[j].top & 3) == 2) {
                    //前面的转换已经把l可能产生的贡献已经清除了
                    ans[tq[j].top >> 2] -= sum(tq[j].d1);
                } else if((tq[j].top & 3) == 3) {
                    ans[tq[j].top >> 2] += sum(tq[j].d1);
                    //op2和op3都是成对出现的,只对其中一个赋值就可以了
                    vis[tq[j].top >> 2] = true;
                }
            }
        }
    
        if(!fl) {
            if(cnt < BUILDLIMIT) {
                for(int j = 1; j <= top; ++j) {
                    //对应撤销修改操作
                    if((tq[j].top & 3) == 1)
                        add(tq[j].d1, -1);
                    else if((tq[j].top & 3) == 0)
                        add(tq[j].d1, +1);
                }
            } else {
                //直接重建
                clear();
            }
            merge(q + l, q + mid + 1, q + mid + 1, q + r + 1, tq + 1);
            for(int j = l; j <= r; ++j)
                q[j] = tq[j - l + 1];
        }
        return;
    }
    
    int a[MAXN + 5], b[MAXN + 5];
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
    
        int n, m;
        Read(n), Read(m);
        int qtop = 0;
    
        for(int i = 1; i <= n; ++i) {
            Read(a[i]);
            b[i] = (a[i] == a[i - 1]) ? 0 : a[i];
    
            q[++qtop].top = 1;
            q[qtop].x = i;
            q[qtop].d1 = b[i] + 1;
        }
    
        for(int i = 1, op; i <= m; ++i) {
            Read(op);
            if(op == 1) {
                int x, y;
                Read(x), Read(y);
                q[++qtop].top = i << 2;
                q[qtop].x = x;
                q[qtop].d1 = b[x] + 1;
    
                q[++qtop].top = i << 2;
                q[qtop].x = x + 1;
                q[qtop].d1 = b[x + 1] + 1;
    
                a[x] = y;
                b[x] = (a[x] == a[x - 1]) ? 0 : a[x];
                b[x + 1] = (a[x + 1] == a[x]) ? 0 : a[x + 1];
    
                q[++qtop].top = i << 2 | 1;
                q[qtop].x = x;
                q[qtop].d1 = b[x] + 1;
    
                q[++qtop].top = i << 2 | 1;
                q[qtop].x = x + 1;
                q[qtop].d1 = b[x + 1] + 1;
            } else {
                int l, r, x, y;
                Read(l), Read(r), Read(x), Read(y);
                //op2是要被减去的,op3是要被加上的
                q[++qtop].top = i << 2 | 2;
                //这里询问的就是要l而不是l-1,为了把l可能产生的贡献去掉然后加回来
                q[qtop].x = l;
                q[qtop].d1 = y + 1;
    
                q[++qtop].top = i << 2 | 3;
                //这里询问的就是要l而不是l-1,为了把l可能产生的贡献去掉然后加回来
                q[qtop].x = l;
                q[qtop].d1 = x - 1 + 1;
    
                q[++qtop].top = i << 2 | 3;
                q[qtop].x = r;
                q[qtop].d1 = y + 1;
    
                q[++qtop].top = i << 2 | 2;
                q[qtop].x = r;
                q[qtop].d1 = x - 1 + 1;
    
                //把l的贡献加回来
                if(x <= a[l] && a[l] <= y)
                    ++ans[i];
            }
        }
    
        solve(1, qtop, true);
        for(int i = 1; i <= m; ++i) {
            if(vis[i])
                Write(ans[i]);
        }
    }
    

    天使玩偶

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    
    namespace FastIO {
    #define BUF_SIZE 1000000
        bool IOError = 0;
        inline char NextChar() {
            static char buf[BUF_SIZE], *pl = buf + BUF_SIZE, *pr = buf + BUF_SIZE;
            if(pl == pr) {
                pl = buf, pr = buf + fread(buf, 1, BUF_SIZE, stdin);
                if(pr == pl) {
                    IOError = 1;
                    return -1;
                }
            }
            return *pl++;
        }
    #undef BUF_SIZE
    
        inline bool Blank(char c) {
            return c == ' ' || c == '
    ' || c == '
    ' || c == '	';
        }
    
        template<class T> inline void Read(T &x) {
            char c;
            while(Blank(c = NextChar()));
            if(!IOError) {
                for(x = 0; '0' <= c && c <= '9'; c = NextChar())
                    x = (x << 3) + (x << 1) + c - '0';
            }
        }
    
        template<class T> inline void Read2(T &x) {
            char c;
            bool f = 0;
            while(Blank(c = NextChar()));
            if(!IOError) {
                if(c == '-') {
                    f = 1;
                    c = NextChar();
                }
                for(x = 0; '0' <= c && c <= '9'; c = NextChar())
                    x = (x << 3) + (x << 1) + c - '0';
            }
            if(f)
                x = -x;
        }
    
        template<class T> inline void PutChar(T x) {
            if(x > 9)
                PutChar(x / 10);
            putchar(x % 10 + '0');
        }
    
        template<class T> inline void Write(T &x) {
            PutChar(x);
            putchar('
    ');
        }
    
        template<class T> inline void Write2(T &x) {
            if(x < 0) {
                putchar('-');
                PutChar(-x);
            } else
                PutChar(x);
            putchar('
    ');
        }
    }
    
    using namespace FastIO;
    
    const int INF = 0x3f3f3f3f;
    //将题目的[0,1e6]偏移到[1,1e6+1]
    const int H = 1e6 + 1;
    
    int bit[H + 5];
    
    inline void build() {
        memset(bit, INF, sizeof(bit));
    }
    
    void update(int x, int v) {
        for(; x <= H; x += x & -x) {
            if(v < bit[x])
                bit[x] = v;
        }
    }
    
    void unupdate(int x) {
        for(; x <= H; x += x & -x)
            bit[x] = INF;
    }
    
    int query(int x) {
        int res = INF;
        for(; x >= 1; x -= x & -x) {
            if(bit[x] < res)
                res = bit[x];
        }
        return res;
    }
    
    const int MAXNM = 1e6;
    
    struct Query {
        int op, x, y;
        bool operator<(const Query &q)const {
            return x < q.x;
        }
    } q[MAXNM + 5], tq[MAXNM + 5];
    
    inline int before_calc(int l, int r) {
        int mid = (l + r) >> 1;
        int i = l, j = mid + 1, top = 0;
        while(i <= mid || j <= r) {
            if(i > mid || (j <= r && q[j].x < q[i].x)) {
                //把右边的询问加进来
                if((q[j].op & 1) == 0)
                    tq[++top] = q[j];
                ++j;
            } else {
                //把左边的修改加进来
                if((q[i].op & 1) == 1)
                    tq[++top] = q[i];
                ++i;
            }
        }
        return top;
    }
    
    inline void after_calc(int l, int r, int tqtop) {
        int mid = (l + r) >> 1;
        merge(q + l, q + mid + 1, q + mid + 1, q + r + 1, tq + 1);
        for(int j = l; j <= r; ++j)
            q[j] = tq[j - l + 1];
    }
    
    int ans[MAXNM + 5];
    
    //超过该界时不进行取消树状数组,直接重建,因为树状数组有很多加法、判断之类的,而memset快得多
    const int BUILDLIMIT = 5e4;
    
    int calc_upleft(int tqtop) {
        int maxy = -INF;
        for(int i = 1; i <= tqtop; ++i) {
            if(!(tq[i].op & 1))
                maxy = max(maxy, H - tq[i].y + 1);
        }
        if(maxy != INF) {
            int cnt = 0;
            for(int i = 1, nxt; i <= tqtop; i = nxt) {
                for(nxt = i + 1; nxt <= tqtop && tq[i].x == tq[nxt].x; ++nxt);
                for(int j = i; j < nxt; ++j) {
                    if(tq[j].op & 1 && H - tq[j].y + 1 <= maxy) {
                        update(H - tq[j].y + 1, (-tq[j].x + tq[j].y));
                        ++cnt;
                    }
                }
                for(int j = i; j < nxt; ++j) {
                    if(!(tq[j].op & 1))
                        ans[tq[j].op >> 1] = min(ans[tq[j].op >> 1], (tq[j].x - tq[j].y) + query(H - tq[j].y + 1));
    
                }
            }
            if(cnt < BUILDLIMIT) {
                for(int i = 1; i <= tqtop; ++i) {
                    if(tq[i].op & 1 && H - tq[i].y + 1 <= maxy)
                        unupdate(H - tq[i].y + 1);
                }
            } else
                build();
        }
    }
    
    int calc_downleft(int tqtop) {
        int maxy = -INF;
        for(int i = 1; i <= tqtop; ++i) {
            if(!(tq[i].op & 1))
                maxy = max(maxy, tq[i].y);
        }
        if(maxy != INF) {
            int cnt = 0;
            for(int i = 1, nxt; i <= tqtop; i = nxt) {
                for(nxt = i + 1; nxt <= tqtop && tq[i].x == tq[nxt].x; ++nxt);
                for(int j = i; j < nxt; ++j) {
                    if(tq[j].op & 1 && tq[j].y <= maxy) {
                        update(tq[j].y, (-tq[j].x - tq[j].y));
                        ++cnt;
                    }
                }
                for(int j = i; j < nxt; ++j) {
                    if(!(tq[j].op & 1))
                        ans[tq[j].op >> 1] = min(ans[tq[j].op >> 1], (tq[j].x + tq[j].y) + query(tq[j].y));
                }
            }
            if(cnt < BUILDLIMIT) {
                for(int i = 1; i <= tqtop; ++i) {
                    if(tq[i].op & 1 && tq[i].y <= maxy)
                        unupdate(tq[i].y);
                }
            } else
                build();
        }
    }
    
    int calc_upright(int tqtop) {
        int maxy = -INF;
        for(int i = 1; i <= tqtop; ++i) {
            if(!(tq[i].op & 1))
                maxy = max(maxy, H - tq[i].y + 1);
        }
        if(maxy != INF) {
            int cnt = 0;
            for(int i = tqtop, nxt; i >= 1; i = nxt) {
                for(nxt = i - 1; nxt >= 1 && tq[i].x == tq[nxt].x; --nxt);
                for(int j = i; j > nxt; --j) {
                    if(tq[j].op & 1 && H - tq[j].y + 1 <= maxy) {
                        update(H - tq[j].y + 1, (tq[j].x + tq[j].y));
                        ++cnt;
                    }
                }
                for(int j = i; j > nxt; --j) {
                    if(!(tq[j].op & 1))
                        ans[tq[j].op >> 1] = min(ans[tq[j].op >> 1], (-tq[j].x - tq[j].y) + query(H - tq[j].y + 1));
                }
            }
            if(cnt < BUILDLIMIT) {
                for(int i = 1; i <= tqtop; ++i) {
                    if(tq[i].op & 1 && H - tq[i].y + 1 <= maxy)
                        unupdate(H - tq[i].y + 1);
                }
            } else
                build();
        }
    }
    
    int calc_downright(int tqtop) {
        int maxy = -INF;
        for(int i = 1; i <= tqtop; ++i) {
            if(!(tq[i].op & 1))
                maxy = max(maxy, tq[i].y);
        }
        if(maxy != INF) {
            int cnt = 0;
            for(int i = tqtop, nxt; i >= 1; i = nxt) {
                for(nxt = i - 1; nxt >= 1 && tq[i].x == tq[nxt].x; --nxt);
                for(int j = i; j > nxt; --j) {
                    if(tq[j].op & 1 && tq[j].y <= maxy) {
                        ++cnt;
                        update(tq[j].y, (tq[j].x - tq[j].y));
                    }
                }
                for(int j = i; j > nxt; --j) {
                    if(!(tq[j].op & 1))
                        ans[tq[j].op >> 1] = min(ans[tq[j].op >> 1], (-tq[j].x + tq[j].y) + query(tq[j].y));
                }
            }
            if(cnt < BUILDLIMIT) {
                for(int i = 1; i <= tqtop; ++i) {
                    if(tq[i].op & 1 && tq[i].y <= maxy)
                        unupdate(tq[i].y);
                }
            } else
                build();
        }
    }
    
    void solve(int l, int r, bool firstlayer = false) {
        if(l == r)
            return;
        if(!firstlayer) {
            bool all1 = true;
            for(int i = l; i <= r ; i++) {
                if(!(tq[i].op & 1)) {
                    all1 = false;
                    break;
                }
            }
            if(all1) {
                sort(q + l, q + r + 1);
                return;
            }
        }
        int mid = (l + r) >> 1;
        solve(l, mid);
        solve(mid + 1, r);
        //这里是没必要每一层都排序的,事实上是每一层直接归并就可以了
        int tqtop = before_calc(l, r);
        calc_upleft(tqtop);
        calc_downleft(tqtop);
        calc_upright(tqtop);
        calc_downright(tqtop);
        if(!firstlayer)
            after_calc(l, r, tqtop);
        return;
    }
    
    
    int main() {
    #ifdef Yinku
        freopen("Yinku.in", "r", stdin);
    #endif // Yinku
        int n, m;
        Read(n), Read(m);
        //scanf("%d%d", &n, &m);
        int qtop = 0;
        for(int i = 1; i <= n; ++i) {
            int x, y;
            Read(x), Read(y);
            ++qtop;
            q[qtop].op = qtop << 1 | 1;
            q[qtop].x = x + 1;
            q[qtop].y = y + 1;
        }
        for(int i = 1; i <= m; ++i) {
            int op, x, y;
            Read(op), Read(x), Read(y);
            ++qtop;
            q[qtop].op = (qtop << 1) | (op & 1);
            q[qtop].x = x + 1;
            q[qtop].y = y + 1;
        }
        build();
        memset(ans, INF, sizeof(ans[0]) * (n + m + 1));
        solve(1, qtop, true);
        const int MAXANS = 5e6;
        for(int i = 1; i <= qtop; ++i) {
            if(ans[i] <= MAXANS) {
                Write(ans[i]);
            }
        }
    }
    
  • 相关阅读:
    Map集合
    Collections 工具类
    LinkedList 集合
    List集合
    Iterator迭代器
    Collection集合
    时间日期类
    一看就懂!速写docker 容器数据库备份脚本
    Nginx 配置之HTTPS和WSS那些你不知道的事!
    https 证书认证/颁发/秒级认证无烦恼
  • 原文地址:https://www.cnblogs.com/Inko/p/11508283.html
Copyright © 2020-2023  润新知