CF498D Traffic Jams in the Land
用时:40min(看题解了)
线段树,然而思路不太好想,考虑看题解
每个公路有一个拥堵值\(a[i]\),如果当前时间能被\(a[i]\)整除,那么通过这条公路需要\(2\)分钟,否则需要\(1\)分钟,\(2 \le a[i] \le 6\)
由于\(a[i]\)的范围很小,\(lcm(a[i])\)的最大值只有\(60\),所以可以把当前的时间对\(60\)取模。然后随便想想就出来了
维护\(sum[now][i]\)表示节点\(now\)在时刻\(i\)需要花费的时间。
可以得到:\(sum[now][i] = sum[ls][i] + sum[rs][(i+sum[ls][i])\%60]\)
注意,查询城市\((l,r)\)相当于公路\((l,r-1)\)。
空间足够的话就开4倍吧,2倍RE了:(
\(code\)
#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define MogeKo qwq
using namespace std;
const int maxn = 4e5+10;
const int mod = 60;
int n,q,x,y,a[maxn],sum[maxn][70];
char s[10];
#define ls (now<<1)
#define rs (now<<1|1)
#define Mid (l+r>>1)
int read(){
int x = 0,f = 1;
char ch = getchar();
while(ch < '0' || ch > '9'){
if(ch == '-') f = -1;
ch = getchar();
}
while('0' <= ch && ch <= '9'){
x = x*10 + ch-'0';
ch = getchar();
}
return x*f;
}
void pushup(int now){
for(int i = 0;i < mod;i++)
sum[now][i] = sum[ls][i] + sum[rs][(i+sum[ls][i])%mod];
}
void build(int l,int r,int now){
if(l == r){
for(int i = 0;i < mod;i++)
sum[now][i] = 1 + (i%a[l]==0);
return;
}
int mid = Mid;
build(l,mid,ls);
build(mid+1,r,rs);
pushup(now);
}
void modify(int l,int r,int now,int x,int d){
if(l == r){
a[l] = d;
for(int i = 0;i < mod;i++)
sum[now][i] = 1 + (i%a[l]==0);
return;
}
int mid = Mid;
if(x <= mid) modify(l,mid,ls,x,d);
else if(x >= mid+1) modify(mid+1,r,rs,x,d);
pushup(now);
}
int query(int L,int R,int l,int r,int now,int t){
if(L == l && R == r){
return sum[now][t];
}
int mid = Mid;
if(R <= mid) return query(L,R,l,mid,ls,t);
else if(L >= mid+1) return query(L,R,mid+1,r,rs,t);
else {
int ret = query(L,mid,l,mid,ls,t);
ret += query(mid+1,R,mid+1,r,rs,(t+ret)%mod);
return ret;
}
}
int main(){
n = read();
for(int i = 1;i <= n;i++)
a[i] = read();
build(1,n,1);
q = read();
while(q--){
scanf("%s",s);
x = read(), y = read();
if(s[0] == 'A')
printf("%d\n",query(x,y-1,1,n,1,0));
if(s[0] == 'C')
modify(1,n,1,x,y);
}
return 0;
}