zoukankan      html  css  js  c++  java
  • codeforces 914 D Bash and a Tough Math Puzzle

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<algorithm>
     5 #include<cstdio>
     6 using namespace std;
     7 const int N=500100;
     8 int n,a[N],m;
     9 struct tree{
    10     int l,r,gcd;
    11 }tr[N*5];
    12 int gcd(int x,int y){
    13     if(y==0)return x;
    14     else return gcd(y,x%y);
    15 }
    16 void build(int l,int r,int now){
    17     tr[now].l=l;tr[now].r=r;
    18     if(l==r){
    19         tr[now].gcd=a[l];
    20         return;
    21     }
    22     int mid=(l+r)>>1;
    23     build(l,mid,now*2);
    24     build(mid+1,r,now*2+1);
    25     tr[now].gcd=gcd(tr[now*2].gcd,tr[now*2+1].gcd);
    26 }
    27 void change(int x,int y,int now){
    28 //    cout<<tr[now].l<<" "<<tr[now].r<<" "<<x<<endl;
    29     if(tr[now].l==x&&tr[now].r==x){
    30         tr[now].gcd=y;
    31         return ;
    32     }
    33     int mid=(tr[now].l+tr[now].r)>>1;
    34     if(x>mid)change(x,y,now*2+1);
    35     else change(x,y,now*2);
    36     tr[now].gcd=gcd(tr[now*2].gcd,tr[now*2+1].gcd);
    37 }
    38 int check(int l,int r,int x,int now){
    39     if(tr[now].gcd%x==0)return 0;
    40     if(tr[now].l==l&&tr[now].r==r){
    41         if(l==r)return 1;
    42         if(tr[now*2].gcd%x==0)return check(tr[now*2+1].l,tr[now*2+1].r,x,now*2+1);
    43         if(tr[now*2+1].gcd%x==0)return check(tr[now*2].l,tr[now*2].r,x,now*2);
    44         return 2;
    45     }
    46     int mid=(tr[now].l+tr[now].r)>>1;
    47     if(l>mid)return check(l,r,x,now*2+1);
    48     else if(r<=mid)return check(l,r,x,now*2);
    49     else{
    50         return check(l,mid,x,now*2)+check(mid+1,r,x,now*2+1);
    51     } 
    52 }
    53 int main(){
    54     scanf("%d",&n);
    55     for(int i=1;i<=n;i++){
    56         scanf("%d",&a[i]);
    57     }
    58     build(1,n,1);
    59     scanf("%d",&m);
    60     for(int i=1;i<=m;i++){
    61         int k;
    62         scanf("%d",&k);
    63         if(k==1){
    64             int l,r,x;
    65             scanf("%d%d%d",&l,&r,&x);
    66             if(check(l,r,x,1)<=1)printf("YES
    ");
    67             else printf("NO
    ");
    68         }
    69         else{
    70             int x,y;
    71             scanf("%d%d",&x,&y);
    72             change(x,y,1);
    73         }
    74     }
    75     return 0;
    76 }
    View Code

    题意

    •给出一段序列(1≤n≤5*105),两个操作(1≤q≤4*105)

    •操作1 给出l,r,x

    •求区间l-r的gcd,如果至多能改掉区间内的一个数,使gcd是x的倍数,那么输出YES,否则输出NO

    •操作2 给出pos,x

    •将序列中pos位置上的数字改为x

    题解

    线段树,维护区间的gcd

    因为题目询问删除一个数,我们把整个区间分成两块,如果两边的gcd都是x的倍数显然是可以的,如果都不是gcd的倍数,就不行了,因为使两个gcd的gcd为x的倍数,这两个gcd应该都至少含有x因子。如果一个gcd是x的倍数,一个不是,那就递归处理不是的那个区间。

  • 相关阅读:
    Java精选笔记_JSP技术
    Java精选笔记_JavaBean
    Java精选笔记_JSP开发模型
    Java精选笔记_XML基础
    Git_多人协作
    Git_Feature分支
    Git_Bug分支
    Git_分支管理策略
    Git_解决冲突
    Git_创建与合并分支
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9306754.html
Copyright © 2011-2022 走看看