zoukankan      html  css  js  c++  java
  • codeforces 671C

    题意定义f(l,r)为去掉[l,r]部分后剩下的数任意两个数的最大公约数的最大值

    现在求f(l,r)的和

    由于每个数ai最大只有200000,因此我们穷举因子x,记录以其为因子的a[i]的i值并按i升序。

    下面我们从大到小穷举每个因子x,我们依次计算以f(l,r)=x的区间数,

    有了上述的维护信息,我们很容易三种情况的区间满足f(l,r)=x(我就不具体细说了)

    令pre[i]表示当前以第i个位置结尾的区间满足任意j(1<=j<=pre[i]),f(j,i)<x

    显然f(l,r)=x的区间数=当前还没计算过的区间数-∑pre[i]

    这就要维护∑pre[i],每次修改是将一段区间pre[i]>x的数赋值为x

    显然pre[i]是单调不上升,因此可以用线段树维护之

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 typedef long long ll;
     5 int laz[200010*4],mi[200010*4],mx[200010*4];
     6 ll tr[200010*4];
     7 vector<int> g[200010];
     8 int n,m;
     9 void build(int i,int l,int r)
    10 {
    11     laz[i]=-1;
    12     if (l==r) mx[i]=mi[i]=tr[i]=l;
    13     else {
    14         int m=(l+r)>>1;
    15         build(i*2,l,m);
    16         build(i*2+1,m+1,r);
    17         tr[i]=tr[i*2]+tr[i*2+1];
    18         mx[i]=max(mx[i*2],mx[i*2+1]);
    19         mi[i]=min(mi[i*2],mi[i*2+1]);
    20     }
    21 }
    22 
    23 void work(int i,int l,int r,int x,int y,int z)
    24 {
    25    // if (i==1) cout <<z<<endl;
    26     if (x>y) return;
    27     if (mx[i]<=z) return;
    28     if (x<=l&&y>=r&&mi[i]>z)
    29     {
    30         mi[i]=mx[i]=laz[i]=z;
    31         tr[i]=(ll)(r-l+1)*z;
    32     }
    33     else {
    34         int m=(l+r)>>1;
    35         if (laz[i]>-1)
    36         {
    37             laz[i*2]=laz[i*2+1]=laz[i];
    38             mi[i*2]=mx[i*2]=laz[i];
    39             mi[i*2+1]=mx[i*2+1]=laz[i];
    40             tr[i*2]=(ll)laz[i]*(m-l+1);
    41             tr[i*2+1]=(ll)laz[i]*(r-m);
    42             laz[i]=-1;
    43         }
    44         if (x<=m) work(i*2,l,m,x,y,z);
    45         if (y>m) work(i*2+1,m+1,r,x,y,z);
    46         tr[i]=tr[i*2]+tr[i*2+1];
    47         mx[i]=max(mx[i*2],mx[i*2+1]);
    48         mi[i]=min(mi[i*2],mi[i*2+1]);
    49     }
    50 }
    51 
    52 int main()
    53 {
    54     scanf("%d",&n);
    55     for (int i=1; i<=n; i++)
    56     {
    57         int x;scanf("%d",&x);
    58         for (int j=1; j*j<=x; j++)
    59             if (x%j==0)
    60             {
    61                 g[x/j].push_back(i);
    62                 if (j*j!=x) g[j].push_back(i);
    63             }
    64         m=max(m,x);
    65     }
    66     build(1,1,n);
    67     ll pre=(ll)n*(n+1)/2;
    68     ll ans=0;
    69     for (int i=m; i; i--)
    70     {
    71         if (g[i].size()<2) continue;
    72         int j=g[i].size()-1;
    73         work(1,1,n,g[i][0]+1,g[i][j]-1,g[i][0]);
    74         work(1,1,n,1,g[i][j-1]-1,0);
    75         work(1,1,n,g[i][1]+1,n,g[i][1]);
    76         ans+=(pre-tr[1])*(ll)i;
    77        // cout <<tr[1]<<endl;
    78         pre=tr[1];
    79     }
    80     printf("%lld
    ",ans);
    81 }
    View Code
  • 相关阅读:
    Gin-Go学习笔记六:Gin-Web框架 Api的编写
    Gin-Go学习笔记五:Gin-Web框架 文件的操作
    Gin-Go学习笔记四:Gin-Web框架 文件的上传下载
    Gin-Go学习笔记三:Gin-Web框架 JS分页
    Gin-Go学习笔记二:Gin-Web框架
    Gin-Go学习笔记一:Hello World
    质因数分解
    素数算法
    linux-cento os学习笔记1
    python运行代码出现'ascii' codec can't decode byte 0xb4 in position 11: ordinal not in range(128)
  • 原文地址:https://www.cnblogs.com/phile/p/6354666.html
Copyright © 2011-2022 走看看