您的位置:首页 > 其它

codeforces 498 d Traffic Jams in the Land

2014-12-30 12:00 465 查看
codeforces 498 d Traffic Jams in the Land

题目链接

点击打开链接

题意:有n+1个城市,n条路,每条路连着第n个和第n+1个城市,然后每条路有一个路况信息a[i],如果现在的时刻t,t%a[i]==0,则不能通过这条路,要等到下一秒t+1,如果现在时刻t,t%a[i]!=0,则通过这条路,花费时间为1。现在有q个操作,对于每个操作有两种类型:

A x y 询问从城市x到城市y要花费多少时间

C x y 把a[x]改为y

限制:1 <= n <= 1e5 , 2 <= ai <= 6 , 1 <= q <= 1e5

思路:线段树

要解决的问题是O(logn)查询出来从x到y的时间。

因为ai只有 2 3 4 5 6 这几个取值,最小公倍数为60,也就是说无论是哪段路都可以以60为周期。

所以对路建树

线段树里面有一个t[60]的数组,表示在l城市在t时刻出发到r+1城市要花的时间。

考虑好向上维护的情况就能过了。

/*cf284div1d
题意:有n+1个城市,n条路,每条路连着第n个和第n+1个城市,然后每条路有一个路况信息a[i],如果现在的时刻t,t%a[i]==0,则不能通过这条路,要等到下一秒t+1,如果现在时刻t,t%a[i]!=0,则通过这条路,花费时间为1。现在有q个操作,对于美国操作有两种类型:
A x y 询问从城市x到城市y要花费多少时间
C x y 把a[x]改为y
限制:1 <= n <= 1e5 , 2 <= ai <= 6 , 1 <= q <= 1e5
思路:线段树
要解决的问题是O(logn)查询出来从x到y的时间。
因为ai只有 2 3 4 5 6 这几个取值,最小公倍数为60,也就是说无论是哪段路都可以以60为周期。
所以对路建树
线段树里面有一个t[60]的数组,表示在l城市在t时刻出发到r+1城市要花的时间。
考虑好向上维护的情况就能过了。
*/
#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
int a
;
struct Seg{
int l,r,mid;
int t[60];
}seg[3*N];
void up(int n){
for(int i=0;i<60;++i){
int tmp=i+seg[2*n].t[i];	//注意的地方
seg
.t[i]=tmp-i+seg[2*n+1].t[tmp%60];
}
}
void build(int l,int r,int n){
seg
.l=l; seg
.r=r; seg
.mid=(l+r)>>1;
if(l==r){
for(int i=0;i<60;++i)
if(i%a[l]==0) seg
.t[i]=2;
else seg
.t[i]=1;
return ;
}
build(l,seg
.mid,2*n);
build(seg
.mid+1,r,2*n+1);
up(n);
}
void update(int u,int n,int x){
if(seg
.l==seg
.r){
a[u]=x;
for(int i=0;i<60;++i)
if(i%a[u]==0) seg
.t[i]=2;
else seg
.t[i]=1;
return ;
}
if(u<=seg
.mid) update(u,2*n,x);
else update(u,2*n+1,x);
up(n);
}
int query(int l,int r,int n,int t){
if(l <= seg
.l && seg
.r <= r){
return t+seg
.t[t%60];
}
if(seg
.mid>=l) t=query(l,r,2*n,t);
if(seg
.mid<r) t=query(l,r,2*n+1,t);
return t;
}
void debug(int n){
cout<<"---"<<endl;
for(int i=1;i<=n;++i)
cout<<query(i,i,1,0)<<' ';
cout<<endl;
cout<<"---"<<endl;
}
void debug1(int n){
cout<<seg
.l<<' '<<seg
.r<<' '<<seg
.t[0]<<endl;
if(seg
.l==seg
.r) return ;
debug1(2*n);
debug1(2*n+1);
}
int main(){
int n;
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d",&a[i]);
build(1,n,1);
int m;
scanf("%d",&m);
char op[2];
int u,v;
for(int i=0;i<m;++i){
scanf("%s%d%d",op,&u,&v);
if(op[0]=='A'){
printf("%d\n",query(u,v-1,1,0));
}
else{
update(u,1,v);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: