此题确实是妙,用到了题目的每一个小细节
先是全题的重中之重,对于每一条路,他的拥堵值一定小于等于6
这意味着什么,因为要对拥堵值取模,我们的累计时间就可以提前进行取模
这样就可以表示出该节点的状态了
讲的比较混乱,我们来说代码
我们使用线段树,区间权值的意义是,在时间
i
i
i跑到
l
l
l点,到达
r
+
1
r+1
r+1需要多长时间
这样对于查询操作我们只需要区间求和即可
如何实现呢,我们前面也说了,枚举当前点的每一种情况,
l
c
m
(
1
,
2
,
3
,
4
,
5
,
6
)
=
60
lcm {(1,2,3,4,5,6 )}=60
lcm(1,2,3,4,5,6)=60
这又意味着啥呢,对于时间,我们可以直接取模60,不影响整除结果
我们就可以表示出所有状态了
这样他的pushup就长这样
void pushup(int k){
for(int i=0;i<=59;i++){
tr[k].val[i]=tr[lch(k)].val[i]+tr[rch(k)].val[(tr[lch(k)].val[i]+i)%mod];
}
return;
}
是不是豁然开朗,当然,修改权值的时候也要全部给底层点更新才行,和建树时一模一样
其他的小技巧看代码即可
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define lch(x) x*2
#define rch(x) x*2+1
using namespace std;
const int mod = 60;
const int maxn = 200005;
int n,m,val[maxn];
struct node{
int l,r,val[61];
}tr[maxn*3];
inline int read(){
int f=1,x=0;char ch;
do{ch=getchar();if(ch=='-')f=-1;}while(ch<'0'||ch>'9');
do{x=x*10+ch-'0';ch=getchar();}while(ch>='0'&&ch<='9');
return f*x;
}
void pushup(int k){
for(int i=0;i<=59;i++){
tr[k].val[i]=tr[lch(k)].val[i]+tr[rch(k)].val[(tr[lch(k)].val[i]+i)%mod];
}
return;
}
void build(int k,int l,int r){
tr[k].l=l;
tr[k].r=r;
if(l==r){
for(int i=0;i<=59;i++){
tr[k].val[i]=1+(i%val[l]==0);
}
return ;
}
int mid=l+r>>1;
build(lch(k),l,mid);
build(rch(k),mid+1,r);
pushup(k);
}
void modi(int k,int x,int num){
int l=tr[k].l;
int r=tr[k].r;
if(l==r&&l==x){
val[x]=num;
for(int i=0;i<=59;i++){// 全部更新
tr[k].val[i]=1+(i%num==0);
}
return ;
}
int mid=l+r>>1;
if(x<=mid)modi(lch(k),x,num);
else modi(rch(k),x,num);
pushup(k);
}
int que(int k,int x,int y,int times){
int l=tr[k].l;
int r=tr[k].r;
if(l>y||r<x)return 0;
if(x<=l&&y>=r)return tr[k].val[times];
int mid=l+r>>1,res=0;
res=que(lch(k),x,y,times);// 更新累计时间
return res+que(rch(k),x,y,(times+res)%60);// 这里别忘了取模
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&val[i]);
}
build(1,1,n);
scanf("%d",&m);
for(int i=1;i<=m;i++){
string aa;
int b,c;
cin>>aa>>b>>c;
if(aa[0]=='A'){
c--;// 是统计这一点之前的哦,我门等于运用了边换点的思想
printf("%d\n",que(1,b,c,0));
}
else {
modi(1,b,c);
}
}
return 0;
}