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
  • 相关阅读:
    centos 安装 TortoiseSVN svn 客户端
    linux 定时任务 日志记录
    centos6.5 安装PHP7.0支持nginx
    linux root 用户 定时任务添加
    composer 一些使用说明
    laravel cookie写入
    laravel composer 安装指定版本以及基本的配置
    mysql 删除重复记录语句
    linux php redis 扩展安装
    linux php 安装 memcache 扩展
  • 原文地址:https://www.cnblogs.com/phile/p/6354666.html
Copyright © 2011-2022 走看看