正题
luogu
CF498D
题目大意
给n个1-6的数,让你进行以下操作:
- 修改其中一个数
- 从第x个数走到第y个数(x≤yx\leq yx≤y),到达一个点时,如果当前时间能被该数整除,那么时间+2,否则+1(初始时间为0),问走到y的时间
解题思路
因为每个数 ≤6\leq 6≤6,所以可以求出1-6的lcm为60,计算时只要知道时间对60取模的结果就可以知道是否会被整除
考虑使用线段树,每个点维护当前区间开始时时间模60的结果会使用的时间即可
时间复杂度 O(60×nlogn)O(60\times n\ log\ n)O(60×n log n)
code
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
#define N 100100
using namespace std;
int n,t,x,y,v[N];
char c[N];
struct node
{int a[65];
};
node merge(node a,node b)
{node c;for(int i=0;i<60;++i)c.a[i]=a.a[i]+b.a[(i+a.a[i])%60];return c;
}
struct Tree
{#define ls x*2#define rs x*2+1node s[N<<2];void push_up(int x){s[x]=merge(s[ls],s[rs]);return;}void get(int x,int y){for(int i=0;i<60;++i)s[x].a[i]=1;for(int i=0;i*y<60;++i)s[x].a[i*y]=2;return;}void build(int x,int l,int r){if(l==r){get(x,v[l]);return;}int mid=l+r>>1;build(ls,l,mid);build(rs,mid+1,r);push_up(x);return;}void change(int x,int l,int r,int y,int z){if(l==r){get(x,z);return;}int mid=l+r>>1;if(y<=mid)change(ls,l,mid,y,z);else change(rs,mid+1,r,y,z);push_up(x);return;}node ask(int x,int L,int R,int l,int r){if(L==l&&R==r)return s[x];int mid=L+R>>1;if(r<=mid)return ask(ls,L,mid,l,r);else if(l>mid)return ask(rs,mid+1,R,l,r);else return merge(ask(ls,L,mid,l,mid),ask(rs,mid+1,R,mid+1,r));}
}T;
int main()
{scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%d",&v[i]);T.build(1,1,n);scanf("%d",&t);while(t--){scanf("%s%d%d",c,&x,&y);if(c[0]=='C')T.change(1,1,n,x,y);else printf("%d\n",T.ask(1,1,n,x,y-1).a[0]);}return 0;
}