zoukankan      html  css  js  c++  java
  • 【线段树 经典技巧】10.7序列绝对值

    依旧是经典的线段树处理新定义权值以及拆绝对值技巧

    不过稍微有些细节

    题目大意

    初始先给定一个序列$A$,定义一个序列的绝对权值为$sumlimits_{i=2}^n|a_i-a_{i-1}|$.

    现在有$q$次操作,每个操作或是询问如果在$A[l,r]$任选一个数加上$x$,$A$的绝对权值最大是多少;或区间加。

    $n,qle 10^5$,保证$1<lle r<n$.


    题目分析

    首先这是一个经典的线段树处理新定义权值最值的问题。

    考虑一个$i$位置权值为$B$,它的左右权值分别是$A,C$,那么现在如果把它变成数$X$,为答案造成的贡献就是$(|X-A|+|X-C|)-(|B-A|+|B-C|)$.

    定义$wrin(i)=(|B-A|+|B-C|)$,处理后贡献式子就是

    $=max{A+C-2*X,-A-C+2*X,(max{A,C}-min{A,C})}-wrin(i)$

    其中对于每一个位置来说,$A+C$或者$|A-C|$都是方便维护的常量。因此只需要记录区间内$max{A+C},max{-A-C},max{|A-C|}$这三个量就能够处理询问了。

    接下来考虑如何修改。

    对于修改的区间$[L,R]$,它对上述的三个量都会在$L-1,L,R,R+1$四个单点位置有变化,并且前两个量还有$[L,R]$的整段增量。也就是说要维护区间/单点加和区间最大值的线段树。

    还有一个小点就是要处理每次修改后的全局权值,也就是说要询问某一位置元素的权值。这个由于对区间元素的修改是区间的,而查询元素是单点的,所以用树状数组累计一下差分后的数组就好了。

      1 #include<bits/stdc++.h>
      2 typedef long long ll;
      3 const int maxn = 100035;
      4 
      5 int n,q;
      6 ll ans,val,a[maxn],num[maxn];
      7 ll abs(ll x){return x > 0?x:-x;}
      8 struct SegTree
      9 {
     10     ll f[maxn<<2],add[maxn<<2];
     11     
     12     void pushup(int rt)
     13     {
     14         f[rt] = std::max(f[rt<<1], f[rt<<1|1]);
     15     }
     16     void pushdown(int rt)
     17     {
     18         if (add[rt]){
     19             int l = rt<<1, r = rt<<1|1;
     20             ll &tag = add[rt];
     21             add[l] += tag, add[r] += tag;
     22             f[l] += tag, f[r] += tag, tag = 0;
     23         }
     24     }
     25     void build(int rt, int l, int r, ll c)
     26     {
     27         if (l==r){
     28             f[rt] = (a[l-1]+a[l+1])*c-abs(a[l]-a[l-1])-abs(a[l]-a[l+1])-2*c*a[l];
     29             if (c==0) f[rt] = abs(a[l+1]-a[l-1])-abs(a[l]-a[l-1])-abs(a[l]-a[l+1]);
     30         }else{
     31             int mid = (l+r)>>1;
     32             build(rt<<1, l, mid, c);
     33             build(rt<<1|1, mid+1, r, c);
     34             pushup(rt);
     35         }
     36     }
     37     void modify(int rt, int L, int R, int l, int r, ll c)
     38     {
     39         if (L <= l&&r <= R){
     40             f[rt] += c, add[rt] += c;
     41         }else{
     42             int mid = (l+r)>>1;
     43             pushdown(rt);
     44             if (L <= mid) modify(rt<<1, L, R, l, mid, c);
     45             if (R > mid) modify(rt<<1|1, L, R, mid+1, r, c);
     46             pushup(rt);
     47         }
     48     }
     49     void modify(int rt, int l, int r, int pos, ll c)
     50     {
     51         if (l==r) f[rt] += c;
     52         else{
     53             int mid = (l+r)>>1;
     54             pushdown(rt);
     55             if (pos <= mid) modify(rt<<1, l, mid, pos, c);
     56             else modify(rt<<1|1, mid+1, r, pos, c);
     57             pushup(rt);
     58         }
     59     }
     60     ll query(int rt, int L, int R, int l, int r)
     61     {
     62         if (L <= l&&r <= R) return f[rt];
     63         int mid = (l+r)>>1;
     64         ll ret = -(1ll<<60);
     65         pushdown(rt);
     66         if (L <= mid) ret = query(rt<<1, L, R, l, mid);
     67         if (R > mid) ret = std::max(ret, query(rt<<1|1, L, R, mid+1, r));
     68         return ret;
     69     }
     70 }f,g,h;
     71 
     72 int read()
     73 {
     74     char ch = getchar();
     75     int num = 0, fl = 1;
     76     for (; !isdigit(ch); ch=getchar())
     77         if (ch=='-') fl = -1;
     78     for (; isdigit(ch); ch=getchar())
     79         num = (num<<1)+(num<<3)+ch-48;
     80     return num*fl;
     81 }
     82 void add(int x, ll c){for (; x<=n; x+=x&-x) num[x] += c;}
     83 ll query(int x)                                //之前这里query类型写成int...
     84 {
     85     ll ret = 0;
     86     for (; x; x-=x&-x) ret += num[x];
     87     return ret;
     88 }
     89 int main()
     90 {
     91     n = read(); 
     92     for (int i=1; i<=n; i++) a[i] = read();
     93     for (int i=1; i<=n; i++)
     94         add(i, a[i]-a[i-1]), 
     95         val += i!=n?abs(a[i]-a[i+1]):0;
     96     f.build(1, 1, n, 1);
     97     g.build(1, 1, n, -1);
     98     h.build(1, 1, n, 0);
     99     q = read();
    100     for (int opt,l,r,x; q; --q)
    101     {
    102         opt = read(), l = read(), r = read(), x = read();
    103         if (opt==1){
    104             ans = std::max(h.query(1, l, r, 1, n), std::max(f.query(1, l, r, 1, n)-2ll*x, g.query(1, l, r, 1, n)+2ll*x))+val;
    105             printf("%lld
    ",ans);
    106         }else{
    107             f.modify(1, l, r, 1, n, -2ll*x);
    108             g.modify(1, l, r, 1, n, 2ll*x);
    109             f.modify(1, l-1, r-1, 1, n, x);
    110             g.modify(1, l+1, r+1, 1, n, -x);
    111             f.modify(1, l+1, r+1, 1, n, x);
    112             g.modify(1, l-1, r-1, 1, n, -x);
    113             ll p1 = query(l-1), p2 = query(l), p3 = query(r), p4 = query(r+1), det = 0;
    114             det = abs(p1-p2-x)-abs(p1-p2), val += det;                //-----wrin-----
    115             f.modify(1, 1, n, l-1, -det);
    116             g.modify(1, 1, n, l-1, -det);
    117             h.modify(1, 1, n, l-1, -det);
    118             f.modify(1, 1, n, l, -det);
    119             g.modify(1, 1, n, l, -det);
    120             h.modify(1, 1, n, l, -det);
    121             det = abs(p4-p3-x)-abs(p4-p3), val += det;
    122             f.modify(1, 1, n, r+1, -det);
    123             g.modify(1, 1, n, r+1, -det);
    124             h.modify(1, 1, n, r+1, -det);
    125             f.modify(1, 1, n, r, -det);
    126             g.modify(1, 1, n, r, -det);
    127             h.modify(1, 1, n, r, -det);                                //-----wrin-----
    128             ll p5 = query(l-2), p6 = query(l+1), p7 = query(r-1), p8 = query(r+2);  //容易写成a[..]
    129             det = abs(p5-p2)-abs(p5-p2-x);          //因为左右两个元素并不知道大小关系
    130             h.modify(1, 1, n, l-1, -det);
    131             if (l!=r){
    132                 det = abs(p1-p6)-abs(p1-p6-x);
    133                 h.modify(1, 1, n, l, -det);
    134                 det = abs(p4-p7)-abs(p4-p7-x);
    135                 h.modify(1, 1, n, r, -det);
    136             }
    137             det = abs(p8-p3)-abs(p8-p3-x);
    138             h.modify(1, 1, n, r+1, -det);
    139             add(l, x), add(r+1, -x);
    140         }
    141     }
    142     return 0;
    143 } 

    END

  • 相关阅读:
    Saltstack module acl 详解
    Saltstack python client
    Saltstack简单使用
    P5488 差分与前缀和 NTT Lucas定理 多项式
    CF613D Kingdom and its Cities 虚树 树形dp 贪心
    7.1 NOI模拟赛 凸包套凸包 floyd 计算几何
    luogu P5633 最小度限制生成树 wqs二分
    7.1 NOI模拟赛 dp floyd
    springboot和springcloud
    springboot集成mybatis
  • 原文地址:https://www.cnblogs.com/antiquality/p/11630722.html
Copyright © 2011-2022 走看看