zoukankan      html  css  js  c++  java
  • Luogu P1438 无聊的数列

    # 解题思路

    这题还是有些恶心的,稍不注意就会 RE 或者是 WA。

    我们先来看看题目中给出的要求:给定等差数列的公差和首项,在给定一个区间,给这个区间加上这个等差数列(逐项)。

    emmmm,考虑一下给一个区间加了一个等差序列之后与原序列相比,有哪些改变,既然是加的等差数列,那每两相邻个数之间的差的变化是一样的,为题目中给出的公差。

    那么也就可以想到用差分数组来做这道题。将原序列的变化搬到差分数组上之后,会发生如下的变化:

    • 差分数组的第一个数肯定要加上 K。
    • 差分数组的 $(L,R]$ 这个区间内,每项都要加上 D。
    • 差分数组的第 $R+1$ 项要减去 $K+D imes (R-L)$

    值得注意的是,在发生后两种变化时要判断区间的类型,如果这个区间的右端点是 $n$,那么我们就不进行第三个变化,如果这个区间的左右端点相等,就不进行第二个变化。

    那从上面来看的话,这个题就是用线段树维护差分数组,支持区间求和和区间加法。

    我写线段树的时候写的懒标记在询问时忘记下传了,233,果然还是我太菜。

    # 附上代码

    给大家看看我奇丑无比自带超大常数的傻逼线段树

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    using namespace std;
    const int maxn = 1e5+3;
    struct node {int l, r, sum, f;} tree[maxn << 2];
    int n, m, a[maxn], d[maxn], tot = 0;
    struct Segment {
        #define Lson (k << 1)
        #define Rson ((k << 1) | 1)
        void read(int &x) {
            x = 0; int f = 1; char c = getchar();
            while (c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
            while (c <= '9' && c >= '0') {x = x*10 + c-'0'; c = getchar();}
            x *= f;
        }
        void build(int k, int ll, int rr) {
            tree[k].l = ll, tree[k].r = rr;
            if(tree[k].l == tree[k].r) {
                tree[k].sum = 0;
                return ;
            }
            int mid = (tree[k].l + tree[k].r) >> 1;
            build(Lson, tree[k].l, mid);
            build(Rson, mid+1, tree[k].r);
            tree[k].sum = tree[Lson].sum + tree[Rson].sum;
        }
        void pushdown(int k) {
            tree[Lson].sum += tree[k].f * (tree[Lson].r - tree[Lson].l + 1);
            tree[Rson].sum += tree[k].f * (tree[Rson].r - tree[Rson].l + 1);
            tree[Lson].f += tree[k].f, tree[Rson].f += tree[k].f;
            tree[k].f = 0;
        }
        void update(int k, int L, int R, int num) {
            if(tree[k].l >= L && tree[k].r <= R) {
                tree[k].sum += (tree[k].r - tree[k].l + 1) * num;
                tree[k].f += num;
                return ;
            }
            if(tree[k].f) pushdown(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) update(Lson, L, R, num);
            if(R > mid) update(Rson, L, R, num);
            tree[k].sum = tree[Lson].sum + tree[Rson].sum;
        }
        int query(int k, int L, int R) {
            int ans = 0;
            if(tree[k].l >= L && tree[k].r <= R)
                return tree[k].sum;
            if(tree[k].f) pushdown(k);
            int mid = (tree[k].l + tree[k].r) >> 1;
            if(L <= mid) ans += query(Lson, L, R);
            if(R > mid) ans += query(Rson, L, R);
            return ans;
        }
        void init() {
            read(n), read(m);
            for(int i=1; i<=n; i++)
                read(a[i]);
        }
        void Query() {
            int opt, l, r, k, D;
            for(int i=1; i<=m; i++) {
                read(opt), read(l);
                if(opt == 1) {
                    read(r), read(k), read(D);
                    update(1, l, l, k);
                    if(r != n) update(1, r+1, r+1, -(k+(r-l)*D));
                    if(r > l) update(1, l+1, r, D);
                }
                else {
                    printf("%d
    ", a[l] + query(1, 1, l));
                }
            }
        }
        Segment () {
            init(), build(1, 1, n);
            Query();
        }
    }T;
    int main() {}
  • 相关阅读:
    基于VB6.0的MICAPS风云二号卫星云图转化实例(转载)
    .CS文件编译生成.DLL文件 .EXE文件(C#网络搜集)(转)
    SQL SERVER 2005及以上查看各表的记录数及占空间大小
    sql2008生成insert语句
    jdk chm文档下载地址
    source insight 解决自动缩进 和 TAB键=4个SPACE
    Hibernate的Criteria的使用
    java多线程协作: wait/notifyAll ( Cooperation between tasks )
    Eclipse 去掉JavaScript Validator
    jquery 插件示例, jquery popup 插件
  • 原文地址:https://www.cnblogs.com/bljfy/p/9783916.html
Copyright © 2011-2022 走看看