[题解]codeforces498d Traffic Jams in the Land

题目:戳这里

Solution

线段树每个节点维护60个值,分别是走到该区间左端时时间为i时该区间所用的时间,因为题目中2<=y<=6,2到6的最小公倍数为60,则走过的时间在判断是否堵车是可以mod 60。

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

const int maxn=100010;
struct Data{
    int t[60];
    Data(){memset(t,0,sizeof t);}
};
struct Segment_Tree{
    #define lc x<<1
    #define rc x<<1|1
    int L[maxn<<2],R[maxn<<2];
    Data res[maxn<<2];
    void update(int x){
        for(int i=0;i<60;i++)
            res[x].t[i]=res[lc].t[i]+res[rc].t[(i+res[lc].t[i])%60];
    }
    void Build(int x,int *a,int l,int r){
        if((L[x]=l)==(R[x]=r)){
            for(int i=0;i<60;i++)
                if(i%a[l])res[x].t[i]=1;
                else res[x].t[i]=2;
            return;
        }
        int mid=(l+r)>>1;
        Build(lc,a,l,mid);Build(rc,a,mid+1,r);
        update(x);
    }
    void Change(int x,int pos,int val){
        if(L[x]==R[x]){
            for(int i=0;i<60;i++)
                if(i%val)res[x].t[i]=1;
                else res[x].t[i]=2;
            return;
        }
        int mid=(L[x]+R[x])>>1;
        if(pos<=mid)Change(lc,pos,val);
        else Change(rc,pos,val);
        update(x);
    }
    Data Query(int x,int l,int r){
        if(L[x]>=l&&R[x]<=r)return res[x];
        int mid=(L[x]+R[x])>>1;
        Data temp,ls,rs;
        if(l<=mid&&r>mid){
            ls=Query(lc,l,r);rs=Query(rc,l,r);
            for(int i=0;i<60;i++)
                temp.t[i]=ls.t[i]+rs.t[(i+ls.t[i])%60];
            return temp;
        }
        else if(l<=mid)return Query(lc,l,r);
        else return Query(rc,l,r);
    }
}tree;
int n,m,a[maxn];

int main(){ 
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    tree.Build(1,a,1,n);
    scanf("%d",&m);
    while(m--){
        char opt[5];int x,y;
        scanf("%s%d%d",opt,&x,&y);
        if(opt[0]=='A')printf("%d\n",tree.Query(1,x,y-1).t[0]);
        else if(opt[0]=='C')tree.Change(1,x,y);
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值