• CF671C Ultimate Weirdness of an Array 题解


    Codeforces
    Luogu

    Description.

    对于所有区间,权值定义为它补集中两两 \(\gcd\) 最大值。
    求所有区间和,如果补集大小 \(\le 1\) 则直接当作 \(0\)

    Solution.

    差分,要求满足 \(\gcd <=k\) 的区间有多少个
    发现区间从左往右值单调不下降
    所以在 \(k\) 减小时每个区间会向右扩展
    当前 \(\gcd = k\),找到所有 \(k\) 的倍数
    找到第二个 \(k\) 的倍数,它之后区间覆盖成 \(n\)
    第一个 \(k\) 和第二个 \(k\) 之间的右端点会 \(= \max(a_i,firlas)\)
    左端的相当于右端点 \(= \max(a_i,seclas)\)
    然后就做完了。
    根本不需要吉司机,其实可以直接线段树二分。
    因为权值必定单调。

    Coding.

    点击查看代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=200005;int n,a[N],mx;vector<int>v[N];
    struct seg{ll sm;int mx,ln,fg;}T[N<<2];ll cf[N];
    inline void pushup(int x) {T[x].mx=max(T[x<<1].mx,T[x<<1|1].mx),T[x].sm=T[x<<1].sm+T[x<<1|1].sm;}
    inline void allc(int x,int c) {T[x].sm=1ll*c*T[x].ln,T[x].fg=T[x].mx=c;}
    inline void pushdw(int x) {if(T[x].fg) allc(x<<1,T[x].fg),allc(x<<1|1,T[x].fg),T[x].fg=0;}
    inline void build(int x,int l,int r)
    {
    	T[x].ln=r-l+1;if(l==r) return T[x].sm=T[x].mx=l,void();
    	build(x<<1,l,(l+r)>>1),build(x<<1|1,((l+r)>>1)+1,r),pushup(x);
    }
    inline void modiff(int x,int l,int r,int dl,int dr,int dc)
    {
    	if(l>dr||dl>r) return;else if(dl<=l&&r<=dr) return allc(x,dc);else pushdw(x);
    	modiff(x<<1,l,(l+r)>>1,dl,dr,dc),modiff(x<<1|1,((l+r)>>1)+1,r,dl,dr,dc),pushup(x);
    }
    inline void modif(int x,int l,int r,int dl,int dr,int dc)
    {
    	if(l>dr||dl>r) return;else if(l==r) return T[x].sm=T[x].mx=max(T[x].mx,dc),void();
    	pushdw(x);if(T[x<<1].mx>dc) return modif(x<<1,l,(l+r)>>1,dl,dr,dc),pushup(x);
    	modiff(x<<1,l,(l+r)>>1,dl,dr,dc),modif(x<<1|1,((l+r)>>1)+1,r,dl,dr,dc),pushup(x);
    }
    inline void debug(int x,int l,int r)
    {
    	//printf("[ %d %d ] : %lld ( %d %d\n",l,r,T[x].sm,T[x].ln,T[x].mx);
    	if(l==r) return printf("%d%c",T[x].mx,l==n?'\n':' '),void();
    	pushdw(x),debug(x<<1,l,(l+r)>>1),debug(x<<1|1,((l+r)>>1)+1,r);
    }
    inline void work(int x)
    {
    	if((int)v[x].size()<=1) return;
    	int fs=v[x][0],sc=v[x][1],sz=v[x].size(),ls=v[x][sz-1],lss=v[x][sz-2];
    	modif(1,1,n,sc+1,n,n+1),modif(1,1,n,fs+1,sc,ls),modif(1,1,n,1,fs,lss);
    	//debug(1,1,n);
    }
    int main()
    {
    	read(n),build(1,1,n);for(int i=1;i<=n;i++) read(a[i]),mx=max(mx,a[i]);
    	for(int i=1;i<=n;i++) for(int j=1;j*j<=a[i];j++)
    		if(a[i]%j==0) {v[j].push_back(i);if(j*j!=a[i]) v[a[i]/j].push_back(i);}
    	cf[mx+1]=T[1].sm;for(int i=mx;i>=1;i--) work(i),cf[i]=T[1].sm;
    	for(int i=1;i<=mx;i++) cf[i]-=cf[i+1];
    	ll rs=0;for(int i=1;i<=mx;i++) rs+=1ll*cf[i]*i;
    	return printf("%lld\n",rs),0;
    }
    
  • 相关阅读:
    河北省重大技术需求征集七稿第二天
    河北省重大技术需求征集七稿第一天
    CNN网络架构演进
    C++学习-类域、友元、运算符重载、对象的生存期,可见域,作用域(2)
    C++学习-类域、友元、运算符重载、对象的生存期,可见域,作用域(1)
    C++学习-输入输出
    C++学习-new delete扩展
    C++学习-类和对象(2)
    C++学习-类和对象(1)
    C++学习-程序内存分配方式
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15382603.html
Copyright © 2020-2023  润新知