牛客 小阳的贝壳 ###K ###K //K

题目链接:https://ac.nowcoder.com/acm/contest/5803/C

思路:根据前两个操作 很容易想到要用线段树来维护一个差分数组

用一个mx 来维护差分区间的最大值即可

要注意的是 最大值的时候取绝对值的时机不要出错 还有差分建树要1到n+1 

剩下关键就是如何要维护区间的gcd了  这里需要知道一个gcd的性质

gcd(a,b)=gcd(a,b-a)   gcd(a,b,c)=gcd(a,b-a,c-b)

可以根据辗转相除法  gcd(a,b)=gcd(b,a%b)   那么就能得gcd(a,b)=gcd(b,a-b)

因为根据取模的含义  a%b=a-k*b  两者在同一个同余系中所以两者gcd一样

因为是有负数之间的gcd 所以要加abs  知道要求的是gcd(a,b-a,c-b)那么就还需要一个sum

维护一个前缀和来得到a  (因为差分的前缀和就是原来的数) 

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define ll long long
  4 #define pb push_back
  5 const int maxn =1e5+10;
  6 const int mod=1e9+7;
  7 ll GCD(ll a,ll b)
  8 {
  9     if(b==0) return a;
 10     else return GCD(b,a%b);
 11 }
 12 int a[maxn];
 13 int n,m;
 14 struct ac
 15 {
 16     int l,r;
 17     ll gcd,mx;
 18     ll sum;
 19 };
 20 ac tree[maxn<<2];
 21 void pushup(int x)
 22 {
 23     tree[x].mx=max(abs(tree[x<<1].mx),abs(tree[x<<1|1].mx));
 24     tree[x].gcd=GCD(tree[x<<1].gcd,tree[x<<1|1].gcd);
 25     tree[x].sum=tree[x<<1].sum+tree[x<<1|1].sum;
 26 }
 27 void build(int x,int l,int r)
 28 {
 29     tree[x].l=l,tree[x].r=r;
 30     if(l==r)
 31     {
 32         tree[x].gcd=a[l];
 33         tree[x].mx=a[l];
 34         tree[x].sum=a[l];
 35     }
 36     else
 37     {
 38         int mid=(l+r)/2;
 39         build(x<<1,l,mid);
 40         build(x<<1|1,mid+1,r);
 41         pushup(x);
 42     }
 43 
 44 }
 45 void update(int x,int pos,int v)
 46 {
 47     int L=tree[x].l,R=tree[x].r;
 48     if(L==R)
 49     {
 50         tree[x].gcd+=v;
 51         tree[x].sum+=v;
 52         tree[x].mx+=v;
 53     }
 54     else
 55     {
 56         int mid=(L+R)/2;
 57         if(pos<=mid) update(x<<1,pos,v);
 58         if(pos>mid) update(x<<1|1,pos,v);
 59         pushup(x);
 60     }
 61 }
 62 ll querymax(int x,int l,int r)
 63 {
 64     int L=tree[x].l,R=tree[x].r;
 65     if(l<=L&&R<=r)
 66     {
 67         return tree[x].mx;
 68     }
 69     else
 70     {
 71         int mid=(L+R)/2;
 72         ll ans=-1;
 73         if(l<=mid) ans=max(ans,abs(querymax(x<<1,l,r)));
 74         if(r>mid) ans=max(ans,abs(querymax(x<<1|1,l,r)));
 75         return ans;
 76     }
 77 }
 78 ll querygcd(int x,int l,int r)
 79 {
 80     int L=tree[x].l,R=tree[x].r;
 81     if(l<=L&&R<=r)
 82     {
 83         return tree[x].gcd;
 84     }
 85     else
 86     {
 87         int mid=(L+R)/2;
 88         ll ans=0;
 89         if(l<=mid) ans=GCD(ans,querygcd(x<<1,l,r));
 90         if(mid<r) ans=GCD(ans,querygcd(x<<1|1,l,r));
 91         return ans;
 92     }
 93 }
 94 ll querysum(int x,int l,int r)
 95 {
 96     int L=tree[x].l,R=tree[x].r;
 97     if(l<=L&&R<=r)
 98     {
 99         return tree[x].sum;
100     }
101     else
102     {
103         int mid=(L+R)/2;
104         ll ans=0;
105         if(l<=mid) ans+=querysum(x<<1,l,r);
106         if(r>mid) ans+=querysum(x<<1|1,l,r);
107         return ans;
108     }
109 }
110 int main()
111 {
112     ios::sync_with_stdio(false);
113     cin.tie(0);
114     cin>>n>>m;
115     for(int i=1;i<=n;i++)
116     {
117         cin>>a[i];
118     }
119     for(int i=n;i>=1;i--)
120     {
121         a[i]=a[i]-a[i-1];
122     }
123     build(1,1,n+1); //因为差分的原因要多后一位
124     while(m--)      // 不然可能会越界
125     {
126         int d,l,r,x;
127         cin>>d>>l>>r;
128         if(d==1)
129         {
130             cin>>x;
131             update(1,l,x);
132             /*if(r==n)  如果建树不用n+1 就要补上这句
133                 continue;*/
134             update(1,r+1,-x);
135         }
136         else if(d==2)
137         {
138             if(l==r)
139                 cout<<0<<'\n';
140             else
141                 cout<<querymax(1,l+1,r)<<'\n';
142         }
143         else
144         {
145             if(l==r)
146             {
147                 cout<<querysum(1,1,l)<<'\n';
148             }
149             else
150             {
151                 ll ans1=querygcd(1,l+1,r);
152                 ll ans2=querysum(1,1,l);
153                 cout<<abs(GCD(ans1,ans2))<<'\n';
154             }
155         }
156     }
157 
158 
159 
160 }
View Code

 

posted @ 2020-06-02 23:03  canwinfor  阅读(183)  评论(0)    收藏  举报