厦门大学“网宿杯“17届程序设计竞赛决赛(同步赛)H.时间管理

时间管理

https://ac.nowcoder.com/acm/contest/5945/H

大致题意:
一个序列,可以执行两种操作。

  • 图片说明 对区间图片说明 内的元素依次对x取图片说明 ,然后将结果赋值给图片说明 .
  • 图片说明 求区间元素和。

图片说明

分析:这道题跟区间开方思路类似。
每次对一个区间进行gcd的话一般会有大部分会变成1,可以用一些小技巧来保证复杂度不会太差,用一个tag变量去标记一下这个区间是不是全都相等,再用一个sam变量去标记区间全相等的时候的元素大小,这样修改的时候对于区间元素都相等的直接对sam进行gcd即可。最后用一个线段树维护标记。(虽然区间开方的题目我是用分块,不过线段树还是挺好写的

#include<bits/stdc++.h>
#define ls cur<<1
#define rs cur<<1|1 
using namespace std;

typedef long long ll;
const int maxn=2e5+10;

ll sum[maxn<<2],a[maxn<<2],ma[maxn<<2],gd[maxn<<2],tag[maxn<<2],sam[maxn<<2];


void pushup( int cur )
{
    sum[cur]=sum[ls]+sum[rs]; 
    tag[cur]=tag[ls] & tag[rs];
    if( tag[cur] ) 
    {
        if( sam[ls]==sam[rs] ) sam[cur]=sam[ls]; 
        else tag[cur]=0;
    }
}

void pushdown( int cur ,int l,int r )
{
    if( tag[cur] )
    {
        int mid=l+r>>1;
        sam[ls]=sam[rs]=sam[cur];
        sum[ls]=(mid-l+1)*sam[ls];
        sum[rs]=(r-mid)*sam[rs];
    }

}

void build( int cur,int l,int r )
{
    if( l==r )
    {
        sum[cur]=a[l];
        tag[cur]=1;
        sam[cur]=a[l];
        return;
    }
    tag[cur]=0;
    int mid=l+r>>1;
    build(ls,l,mid);
    build(rs,mid+1,r);
    pushup(cur);
}

void update( int cur,int l,int r,int L,int R,ll p )
{
    if( L<=l && r<=R )
    {
        if( tag[cur] )
        {
            sam[cur]=__gcd(sam[cur],p);
            sum[cur]=sam[cur]*(r-l+1);
            return;
        }
    }
    pushdown(cur,l,r);
    if( l==r )
    {
        sam[cur]=sum[cur]=__gcd(a[l],p);
        return;
    }
    int mid=l+r>>1;
    if( mid>=L ) update(ls,l,mid,L,R,p);
    if( mid<R )  update(rs,mid+1,r,L,R,p);
    pushup(cur);
}

ll get_sum( int cur,int l,int r,int L,int R )
{
    if( L<=l && r<=R ) return sum[cur];
    int mid=l+r>>1;
    ll ans=0;
    pushdown(cur,l,r);
    if( L<=mid ) ans+=get_sum(ls,l,mid,L,R);
    if( R>mid ) ans+=get_sum(rs,mid+1,r,L,R);
    return ans;
}


int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    for( int i=1;i<=n;i++ ) scanf("%lld",&a[i]);

    build(1,1,n);
    while( m-- )
    {
        int opt,l,r,x;
        scanf("%d%d%d",&opt,&l,&r);
        if( opt==1 )
        {
            ll x;
            scanf("%lld",&x);
            update(1,1,n,l,r,x);
        }
        if( opt==2 ) 
        printf("%lld\n",get_sum(1,1,n,l,r) );
    }
} 
全部评论

相关推荐

ProMonkey2024:5个oc?厉害! 但是有一个小问题:谁问你了?😡我的意思是,谁在意?我告诉你,根本没人问你,在我们之中0人问了你,我把所有问你的人都请来 party 了,到场人数是0个人,誰问你了?WHO ASKED?谁问汝矣?誰があなたに聞きましたか?누가 물어봤어?我爬上了珠穆朗玛峰也没找到谁问你了,我刚刚潜入了世界上最大的射电望远镜也没开到那个问你的人的盒,在找到谁问你之前我连癌症的解药都发明了出来,我开了最大距离渲染也没找到谁问你了我活在这个被辐射蹂躏了多年的破碎世界的坟墓里目睹全球核战争把人类文明毁灭也没见到谁问你了(别的帖子偷来的,现学现卖😋)
点赞 评论 收藏
分享
勇敢的联想人前程似锦:如果我是你,身体素质好我会去参军,然后走士兵计划考研211只需要200多分。
点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务