zoukankan      html  css  js  c++  java
  • CodeForces

    题意:给N个数M次操作,(1<=N,M<=3e5, 1<=ai<=1e6),1是使[L,R]中的每个元素变成其因子的个数之和;2是求[L,R]区间之和

    分析:看上去就很线段树的一题,但是却思考了很久。发现1和2即使对其,也不会改变二者的值。而且一个大于2的数进行多次1操作,也最终会退化到2。

    先预处理筛出1e6以内各数的质因子个数和。在线段树的节点中维护两个值:区间和以及区间最大值。在update函数中,如果该区间的最大值不超过2,那么该区间没有更新的必要;若超过2,则递归向下找到那个位置,并更新它。

    听起来像是退化成了单点更新线段树,其实打个表能发现每个数的因子个数和不会很大,退化几次就成为2了,所以在更新次数很多的情况下,复杂度并不会很高。

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn=3e5+5;
    const int INF =0x3f3f3f3f;
    const int maxv = 1e6+5;
    typedef long long LL;
    struct SGndoe{
        LL sum;
        LL mx;
    }tree[maxn<<4];
    LL a[maxn];
    LL ans[maxv];
    
    void pre()
    {
        for(int i=1;i<=1e6;++i){
            for(int j=0;j<=1e6;j+=i){
                ans[j]++;
            }
        }
    }
    
    void pushup(int root)
    {
        tree[root].sum =tree[root<<1].sum+tree[root<<1|1].sum;
        tree[root].mx = max(tree[root<<1].mx,tree[root<<1|1].mx);
    }
    
    void build(int root,int L,int R){
        if(L==R){
            tree[root].sum = tree[root].mx=a[L];
            return;
        }
        int mid =(L+R)>>1;
        build(root<<1,L,mid);
        build(root<<1|1,mid+1,R);
        pushup(root);
    }
    
    void update(int root,int l,int r,int L,int R)
    {
        if(L<=l && R>=r && tree[root].mx<=2) return;
        else if(l==r){
            tree[root].sum = ans[tree[root].sum];
            tree[root].mx = tree[root].sum;
            return;
        }
        int mid=(l+r)>>1;
        if(L<=mid)update(root<<1,l,mid,L,R);
        if(R>mid) update(root<<1|1,mid+1,r,L,R);
        pushup(root);
    }
    
    LL query(int root,int l,int r,int L,int R)
    {
        if(L<=l&&r<=R) return tree[root].sum;
        int mid=(l+r)>>1;
        LL res=0;
        if(L<=mid) res+=query(root<<1,l,mid,L,R);
        if(mid<R) res+=query(root<<1|1,mid+1,r,L,R);
        return res;
    }
    
    int main(){
        int T,N,M,num,t,x;
        int L,R;
        #ifndef ONLINE_JUDGE
            freopen("in.txt","r",stdin);
            freopen("out.txt","w",stdout);
        #endif
        pre();
        int cas=1;
        while(scanf("%d%d",&N,&M)==2){
            for(int i=1;i<=N;++i) scanf("%lld",&a[i]);
            build(1,1,N);
            int op;
            for(int i=1;i<=M;++i){
                scanf("%d%d%d",&op,&L,&R);
                if(op==1) update(1,1,N,L,R);
                else printf("%lld
    ",query(1,1,N,L,R));
            }
        }
        return 0;
    }
    为了更好的明天
  • 相关阅读:
    Visual Studio “14” CTP 3 Released
    Windows 7 incorrectly reports "No Internet Access"
    How to install SharePoint 2013 on Windows Server 2012 R2
    HOW-TO GEEK SCHOOL
    SharePoint 2013 Support for Windows Server 2012 R2
    Memory Limits for Windows and Windows Server Releases
    Chrome 各版本下载集合
    各大搜索引擎提交网站的入口地址
    简单MVVM教程
    SQL Server 2012 books
  • 原文地址:https://www.cnblogs.com/xiuwenli/p/9387607.html
Copyright © 2011-2022 走看看