• 牛客-小阳的贝壳-区间gcd(线段树)


    链接:https://ac.nowcoder.com/acm/contest/949/H
    来源:牛客网

    题目描述

    小阳手中一共有 n 个贝壳,每个贝壳都有颜色,且初始第 i 个贝壳的颜色为 coli 。现在小阳有 3 种操作:

    1 l r x:给 [l,r] 区间里所有贝壳的颜色值加上 x 。

    2 l r:询问 [l,r] 区间里所有相邻贝壳 颜色值的差(取绝对值) 的最大值(若 l=r 输出 0)。

    3 l r :询问 [l,r] 区间里所有贝壳颜色值的最大公约数。

    输入描述:

    第一行输入两个正整数 n,m,分别表示贝壳个数和操作个数。
    第二行输入 n 个数 coli,表示每个贝壳的初始颜色。
    第三到第 m + 2 行,每行第一个数为 opt,表示操作编号。接下来的输入的变量与操作编号对应。

    输出描述:

    共 m 行,对于每个询问(操作 2 和操作 3)输出对应的结果。
    示例1

    输入

    复制
    5 6
    2 2 3 3 3
    1 2 3 3
    2 2 4
    3 3 5
    1 1 4 2
    3 2 3
    2 3 5

    输出

    复制
    3
    3
    1
    3

    分析:

      这道题线段树,树状数组都用到啦

           核心知识点gcd(a,b)==gcd(a,b-a), 这样的话我们维护一个差分数组,区间修改对于最大公约数的影响可以转化为对点的修改

           a[]: 保存原始数据

           b[]: 保存差分数据 b[i]=a[i]-a[i-1]

           c[]: 当区间【l,r】增加时, c[l]+=x; c[r+1]-=x; 即用树状数组维护a[]数组的区间更改; new_ai=ai+sum{c[x]}  x范围从1到i

      最后用线段树维护最大公约数就好啦

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define lson l,m,rt*2
     4 #define rson m+1,r,rt*2+1
     5 const int N=1e5+7;
     6 int a[N],b[N],c[N];
     7 int tg[4*N],tb[4*N];
     8 int n,m;
     9 inline int gcd (int x, int y) { return y ? gcd(y,x%y) : x; }
    10 void pushup(int rt) {
    11     tg[rt]=gcd(tg[rt*2], tg[rt*2+1]);
    12     tb[rt]=max(abs(tb[rt*2]), abs(tb[rt*2+1]));
    13 }
    14 void build(int l, int r, int rt) {
    15     if (l==r) {
    16         tg[rt]=tb[rt]=b[l];
    17         return ;
    18     }
    19     int m=(l+r)/2;
    20     build(lson);
    21     build(rson);
    22     pushup(rt);
    23     return ;
    24 }
    25 void update(int k, int val, int l, int r, int rt) {
    26     if(l==r) {
    27         tg[rt]+=val;
    28         tb[rt]+=val;
    29         return ;
    30     }
    31     int m=(l+r)/2;
    32     if (k<=m) update(k,val,lson);
    33     else      update(k,val,rson);
    34     pushup(rt);
    35     return ;
    36 }
    37 int q1 (int L, int R, int l, int r, int rt) {
    38     if (r<L||l>R) return 0;
    39     if (l>=L&&r<=R) return abs(tb[rt]);
    40     int m=(l+r)/2;
    41     return max(q1(L,R,lson),q1(L,R,rson));
    42 }
    43 int q2(int L, int R, int l, int r, int rt) {
    44     if (r<L||l>R) return 0;
    45     if (l>=L&&r<=R) return abs(tg[rt]);
    46     int m=(l+r)/2;
    47     int ans1=abs(q2(L,R,lson));
    48     int ans2=abs(q2(L,R,rson));
    49     return gcd(ans1,ans2);
    50 }
    51 void add(int k, int x) {
    52     while (k<=n) {
    53         c[k]+=x;
    54         k+=k&(-k);
    55     }
    56 }
    57 int get_sum(int k) {
    58     int ans=0;
    59     while(k) {
    60         ans+=c[k];
    61         k-=k&(-k);
    62     }
    63     return ans;
    64 }
    65 int main()
    66 {
    67     scanf("%d %d",&n,&m);
    68     for (int i=1;i<=n;i++) {
    69         scanf("%d",&a[i]);
    70         b[i]=a[i]-a[i-1];
    71     }
    72     build(1,n,1);
    73     while (m--) {
    74         int op,l,r; scanf("%d %d %d",&op,&l,&r);
    75         if (op==1) {
    76             int x; scanf("%d",&x);
    77             add(l,x); add(r+1,-x);
    78             update(l,x,1,n,1);
    79             if (r+1<=n) update(r+1,-x,1,n,1);
    80         }
    81         else if (op==2) {
    82             if (l==r) printf("0
    ");
    83             else      printf("%d
    ",q1(l+1,r,1,n,1));
    84         }
    85         else {
    86             int now=a[l]+get_sum(l);
    87             if (l==r) printf("%d
    ",now);
    88             else      printf("%d
    ",gcd(now, q2(l+1,r,1,n,1)));
    89         }
    90     }
    91     return 0;
    92 }
  • 相关阅读:
    ReentrantLock-公平锁、非公平锁、互斥锁、自旋锁
    行动的阻碍
    AQS-等待队列
    AQS-volatile、CAS
    UML类图符号
    最小堆
    红黑树
    Java面试题-Collection框架
    Java面试题-Java特性
    Qt QString中文 char* UTF-8 QByteArray QTextCodec unicode gb2312 GBK 乱码和转码问题
  • 原文地址:https://www.cnblogs.com/xidian-mao/p/11408023.html
Copyright © 2020-2023  润新知