zoukankan      html  css  js  c++  java
  • CF474F Ant colony

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

    题意:

    求区间gcd以及这个区间内的数字等于区间gcd的有多少个(其实是不等于,用区间长度减一下就好了)。

    数据范围:1 ≤ n ≤ 105

    题解

    这题用线段树,但一眼望去这题似乎不满足合并,但实际上是可以的。

    我们在线段树上维护两个东西,一个是区间gcd一个是区间中等于区间gcd的数的个数记为sum。

    考虑如何合并,如果当前区间的两个字区间gcd相等,那么直接把sum相加就好,如果gcd等于两个gcd中的一个,那么sum就是相等gcd对应的那个,如果不相等,那么sum就为0。

    为什么呢?gcd一定小于等于比区间所有数的最小值。gcd合并一定会减少或者不变,不变的话就是第一种情况,减少的话,gcd就比区间的所有数都小,所以区间中就不会有数等于gcd了。

  • 相关阅读:
    在HttpHandlers (ASHX files)中使用Session
    EventCalendar控件源码和ASP.NET 2.0 Beta 2 Starter Kits中可能遇到的问题
    C# 获取数据库中某个某个表的创建脚本[原创]
    Linq 合并多个查询条件
    自定义WCF RIA Services 超时时间
    也来学学插件式开发续利用MEF
    HTML5程序设计 Geolocation API
    反射实体模型生成Oracle SQL脚本
    Entity Framework With Oracle
    Entity Framework Code First在Oracle下的伪实现
  • 原文地址:https://www.cnblogs.com/Xu-daxia/p/9306004.html
Copyright © 2011-2022 走看看