• 【[Ynoi2018]五彩斑斓的世界】


    分块毒瘤题。如果真的想好好练习思维以及代码的话就请不要使用( ext{WC})讲过的黑科技指令集。

    正文部分:

    由乃题必定分块。
    我们可以将同一个块内值相同的用并查集维护起来,因为如果是一个块内相同的值打标机怎么改都一样。
    接着谈修改,我们设块内最大值为( ext{mx}),修改的值为( ext{v})
    如果(v*2>mx)的话就改大于( ext{v})的,否则就改小于( ext{v})
    原理是因为如果大于( ext{v})的比较少的话改大的,否则改小的。
    改小的时候我们可以把小的数全部加上( ext{v}),然后对这个块打上一个减标记。

    My Code:

    // luogu-judger-enable-o2
    #pragma GCC optimize("Ofast,fast-math")
    #pragma GCC target("avx,avx2")
    #include <bits/stdc++.h>
    #define gc (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
    #define _max(x,y) (x > y ? x : y)
    using namespace std;
    static char buf[100000],*p1,*p2;
    static char pbuf[1000000],*pp(pbuf),st[15];
    inline int read() {
        register int res(0);register char c(gc);
        while(c < '0' || c > '9') c = gc;
        while(c >= '0' && c <= '9') res = res * 10 + c - 48,c = gc;
        return res;
    }
    inline void print(register int v) {
        if(!v) *pp++ = 48;
        else { 
            register int tp(0);
           	while(v) st[++tp] = v % 10 + 48,v /= 10;
            while(tp) *pp++ = st[tp--];
        }
        *pp++ = '
    ';
    }
    int fa[100010],a[100010],bel[100010];
    int bl[320],br[320],Max[320],tag[320];
    int root[320][100010];    
    unsigned short cnt[100010];
    int n,m,i,j,k,bls;
    int getf(int o) {
        if(o == fa[o]) return o;
        else return fa[o] = getf(fa[o]);
    }
    inline void build(int num) {
        Max[num] = 0;
        for(register int i = bl[num];i <= br[num];++i) {
            if(!root[num][a[i]]) {
                root[num][a[i]] = i;
                fa[i] = i;
                cnt[root[num][a[i]]] = 1;
            } else {
                fa[i] = root[num][a[i]];
                cnt[root[num][a[i]]]++;
            }
            Max[num] = _max(Max[num],a[i]);
        }
        return;
    }
    inline void pd(int num) {
        for(register int i = bl[num];i <= br[num];++i) {
            a[i] = a[getf(i)];
            cnt[root[num][a[i]]] = 0;root[num][a[i]] = 0;
        }
        for(register int i = bl[num];i <= br[num];++i) {
            a[i] -= tag[num];fa[i] = 0;
        }
        tag[num] = 0;
        return;
    }
    inline void change1(int l,int r,int x) {
        for(register int i = bel[l];i <= bel[r];++i) pd(i); 
        for(register int i = l;i <= r;++i) {
            if(a[i] > x) a[i] -= x;
        }
        for(register int i = bel[l];i <= bel[r];++i) build(i);
        return;
    }
    inline void rpl(int x,int y,int z) {
        if(!root[x][y]) return;
        if(!root[x][z]) {
            root[x][z] = root[x][y];
            cnt[root[x][z]] = cnt[root[x][y]];
            a[root[x][y]] = z;			
        } else {
            fa[root[x][y]] = root[x][z];
            cnt[root[x][z]] += cnt[root[x][y]];
        }
        root[x][y] = 0;
        cnt[root[x][y]] = 0;
        return;
    }
    inline void change2(int num,int val) {
        if(val >= Max[num] - tag[num]) return;
        if(val << 1 > Max[num] - tag[num]) {
            for(register int i = tag[num] + val + 1;i <= Max[num];++i) rpl(num,i,i - val);
         //   Max[num] -= val;Chkmax(Max[num],val + tag[num]);
            Max[num] = _max(Max[num] - val,val + tag[num]);
        } else {
            for(register int i = tag[num] + 1;i <= tag[num] + val;++i) rpl(num,i,i + val);
            tag[num] += val;
        }
        return;
    }
    inline void modify(int l,int r,int x) {
        if(bel[l] + 1 >= bel[r]) {
            change1(l,r,x);
            return;
        }
        change1(l,br[bel[l]],x);change1(bl[bel[r]],r,x);
        for(int i = bel[l] + 1;i < bel[r];++i) change2(i,x);
        return;
    }
    inline int ask1(int l,int r,int x) {
        int res = 0;
        for(int i = l;i <= r;++i) {
            if(a[getf(i)] - tag[bel[i]] == x) res++;
        }
        return res;
    }
    inline int ask2(int num,int val) {
        if(val + tag[num] >= 100000) return 0;
        return cnt[root[num][val + tag[num]]];
    }
    inline int query(int l,int r,int x) {
        if(bel[l] + 1 >= bel[r]) return ask1(l,r,x);
        int res = ask1(l,br[bel[l]],x) + ask1(bl[bel[r]],r,x);         
        for(int i = bel[l] + 1;i < bel[r];i++) res += ask2(i,x);
        return res;
    }
    int main() {
        n = read();m = read();bls = sqrt(n) + 1;
        for(register int i = 1;i <= n;++i) {
            a[i] = read();
            bel[i] = (i - 1) / bls + 1;
            if(!bl[bel[i]]) bl[bel[i]] = i;
            br[bel[i]] = i;
        }
        for(register int i = 1;i <= bel[n];++i) build(i);
       	while(m--) {
            int opt,l,r,x;opt = read();l = read();r = read();x = read();
            if(opt == 1) modify(l,r,x);
            else {
                print(query(l,r,x)); 
            }
        }
        fwrite(pbuf,1,pp-pbuf,stdout);
        return 0;
    }
    
    
  • 相关阅读:
    STL容器 erase的使用陷井
    转:VC++线程同步-事件对象
    VC线程同步方法
    C/C++四种退出线程的方法
    rabbitMQ 常用命令
    Spring @Configuration
    Spring RabbitMQ 延迟队列
    rabbitmq web管理界面 用户管理
    Linux下tar.gz 安装
    Linux下RPM软件包的安装及卸载
  • 原文地址:https://www.cnblogs.com/Sai0511/p/10360348.html
Copyright © 2020-2023  润新知