zoukankan      html  css  js  c++  java
  • loj 数列分块入门 5 7 8

    5

    题意

    给出一个长为(n)的数列,以及(n)个操作,操作涉及区间开方,区间求和。

    思路

    (tag)记录这一块是否已全为(1).

    除分块外,还可用 树状数组+并查集(链表) 或者 线段树 做,见 Educational Codeforces Round 37 F

    Code

    #include <bits/stdc++.h>
    #define maxn 50010
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    using namespace std;
    typedef long long LL;
    int n, blo, a[maxn], sum[maxn], bl[maxn];
    bool tag[maxn];
    void modify(int l, int r) {
        int temp;
        F(i, l, min((bl[l]+1)*blo, r+1)) sum[bl[l]] += (temp=sqrt(a[i]))-a[i], a[i] = temp;
        if (bl[l]!=bl[r]) F2(i, bl[r]*blo, r) sum[bl[r]] += (temp=sqrt(a[i]))-a[i], a[i] = temp;
        F(i, bl[l]+1, bl[r]) {
            if (tag[i]) continue;
            bool flag = true;
            F(j, i*blo, (i+1)*blo) {
                sum[i] += (temp=sqrt(a[j]))-a[j], a[j] = temp;
                if (temp > 1) flag = false;
            }
            tag[i] = flag;
        }
    }
    int query(int l, int r) {
        int ret = 0;
        F(i, l, min((bl[l]+1)*blo, r+1)) ret += a[i];
        if (bl[l]!=bl[r]) F2(i, bl[r]*blo, r) ret += a[i];
        F(i, bl[l]+1, bl[r]) ret += sum[i];
        return ret;
    }
    int main() {
        scanf("%d", &n); blo = sqrt(n);
        F(i, 0, n) scanf("%d", &a[i]), bl[i] = i/blo;
        int num = (n+blo-1) / blo;
        F(i, 0, num-1) {
            F(j, i*blo, (i+1)*blo) sum[i] += a[j];
        }
        F(j, (num-1)*blo, min(num*blo, n+1)) sum[num-1] += a[j];
        F(i, 0, n) {
            int op, l, r, c;
            scanf("%d%d%d%d", &op, &l, &r, &c); --l, --r;
            if (op) printf("%d
    ", query(l, r));
            else modify(l, r);
        }
        return 0;
    }
    
    

    7

    题意

    给出一个长为(n)的数列,以及(n)个操作,操作涉及区间乘法,区间加法,单点询问。

    思路

    (mtag)记录每个块整体的倍数,用(atag)记录每个块整体的增量。
    并且约定(mtag)优先级更高,即真实值为(x*mtag+atag)

    对于不完整的块,先(tag)下放,再直接修改元素;

    对于完整的块,修改(tag)

    1. (+c):即((x*mtag+atag)+c=x*mtag+(atag+c)),于是atag += x;
    2. ( imes c):即((x*mtag+atag)*c=x*(mtag*c)+(atag*c)),于是atag *= x, mtag *= x

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define mod 10007
    #define maxn 100010
    #define maxm 1010
    using namespace std;
    typedef long long LL;
    int n, blo, bl[maxn], a[maxn], mtag[maxm], atag[maxm];
    void reset(int p) {
        F(i, p*blo, (p+1)*blo) {
            (((a[i]*=mtag[p])%=mod)+=atag[p])%=mod;
        }
        mtag[p] = 1, atag[p] = 0;
    }
    void work(int op, int l, int r, int c) {
        reset(bl[l]);
        F(i, l, min(r+1, (bl[l]+1)*blo)) {
            if (op) (a[i]*=c)%=mod;
            else (a[i]+=c)%=mod;
        }
        if (bl[l]!=bl[r]) {
            reset(bl[r]);
            F2(i, bl[r]*blo, r) {
                if (op) (a[i]*=c)%=mod;
                else (a[i]+=c)%=mod;
            }
        }
        F(i, bl[l]+1, bl[r]) {
            if (op) {
                (mtag[i]*=c)%=mod;
                (atag[i]*=c)%=mod;
            }
            else (atag[i]+=c)%=mod;
        }
    }
    int main() {
        scanf("%d", &n); blo = sqrt(n);
        F(i, 0, n) {
            scanf("%d", &a[i]);
            mtag[bl[i] = i/blo] = 1;
        }
        int num=(n+blo-1)/blo;
        F(i, 0, n) {
            int op, l, r, c;
            scanf("%d%d%d%d",&op,&l,&r,&c); --l, --r;
            if (op==2) printf("%d
    ", (a[r]*mtag[bl[r]]%mod+atag[bl[r]])%mod);
            else work(op, l, r, c);
        }
        return 0;
    }
    
    

    8

    题意

    给出一个长为(n)的数列,以及(n)个操作,操作涉及询问等于一个数(c)的元素,并将这个区间的所有元素改为(c).

    思路

    类似上面两题。

    (tag)维护这一块是否均为同一个数。

    对于不完整的块:先下放(tag)后逐个统计修改元素

    对于完整的块:直接针对(tag)进行统计和修改

    Code

    #include <bits/stdc++.h>
    #define F(i, a, b) for (int i = (a); i < (b); ++i)
    #define F2(i, a, b) for (int i = (a); i <= (b); ++i)
    #define dF(i, a, b) for (int i = (a); i > (b); --i)
    #define dF2(i, a, b) for (int i = (a); i >= (b); --i)
    #define maxn 100010
    #define maxm 1010
    using namespace std;
    typedef long long LL;
    int a[maxn], bl[maxn], n, blo, tag[maxm];
    bool flag[maxm];
    void reset(int p) {
        if (!flag[p]) return;
        flag[p] = false;
        F(i, p*blo, min(n, (p+1)*blo)) a[i] = tag[p];
    }
    int query(int l, int r, int c) {
        int ret=0;
        if (flag[bl[l]]&&tag[bl[l]]==c) ret += min(r+1, (bl[l]+1)*blo)-l;
        else {
            reset(bl[l]);
            F(i, l, min(r+1, (bl[l]+1)*blo)) {
                ret += a[i]==c;
                a[i] = c;
            }
        }
        if (bl[l]!=bl[r]) {
            if (flag[bl[r]]&&tag[bl[r]]==c) ret += r-bl[r]*blo+1;
            else {
                reset(bl[r]);
                F2(i, bl[r]*blo, r) {
                    ret += a[i]==c;
                    a[i] = c;
                }
            }
        }
        F(i, bl[l]+1, bl[r]) {
            if (flag[i]) {
                if (tag[i]==c) ret += blo;
            }
            else {
                flag[i] = true;
                F(j, i*blo, (i+1)*blo) ret += a[j]==c;
            }
            tag[i] = c;
        }
        return ret;
    }
    int main() {
        scanf("%d", &n); blo = sqrt(n);
        F(i, 0, n) {
            scanf("%d", &a[i]);
            bl[i] = i/blo;
        }
        int num = (n+blo-1)/blo;
        F(i, 0, n) {
            int l, r, c;
            scanf("%d%d%d", &l,&r,&c);  --l, --r;
            printf("%d
    ", query(l, r, c));
        }
        return 0;
    }
    
    
  • 相关阅读:
    C++异常:exception
    C++关键字:explicit
    C++关键字:重学记录
    Unity jointmoto
    hashtable和hashmap
    Spring MVC 笔记 概述
    SQL上门2
    面试:A
    Java 初学者
    SQL上门
  • 原文地址:https://www.cnblogs.com/kkkkahlua/p/8474278.html
Copyright © 2011-2022 走看看