CF498D:Traffic Jams in the Land——题解

https://vjudge.net/problem/CodeForces-498D

http://codeforces.com/problemset/problem/498/D

题面描述:

一些国家由(n + 1)个城市组成,位于一条直路上。我们用连续的整数从1到n + 1按照高速公路上出现的顺序对城市进行编号。因此,城市由高速公路的n段连接起来,第i段连接城市i和i + 1。高速公路的每一段都与一个正整数ai相关联 - 表示何时交通拥堵期出现在该段上。

为了从城市x到城市y(x <y),一些司机使用以下策略。

最初驾驶员在城市x,当前时间t等于0。在驾驶员抵达城市之前,他会采取以下行动:

1.如果当前时间t是ax的倍数,那么高速公路号x的段现在有交通问题,驾驶员在当前城市停留一个单位时间(当前t = t + 1)。

2.如果当前时间t不是ax的倍数,那么高速公路号x的段现在是畅通的,驾驶员使用一个单位时间移动到城市x + 1(当前t = t + 1且x = x + 1)。

你正在开发一个新的交通控制系统。您要连续处理两种类型的q查询:

A:我们应用上面描述的策略,确定从城市x到城市y(x <y)之后的时间t的最终值。请注意,对于每个查询t初始值为0。

C:用值y替换出现在段号x上的堵塞时段(令ax = y)。

Input

102 5 3 2 3 5 3 4 2 410C 10 6A 2 6A 1 3C 3 4A 3 11A 4 9A 5 6C 7 3A 8 10A 2 5

Output

53146244

这道题还是不是那么好想的……

我们需要发现一个性质:对于0s和60s来说,我们只要走相同的路得到的时间%60都是一样的。

(原因很简单,2-6最小公倍数为60)

所以我们开线段树tree[i][j]表示i区间从js(0<=j<60)开始从头走到尾的最终时间。

build的时候公式如下:

tree[a][i]=tree[a*2+1][tree[a*2][i]%tmax]+tree[a*2][i]/tmax*tmax;

gai的时候和build差不多。

询问的话……看代码吧。

(祝贺60棵线段树AC第一道CF题)

#include<cstdio>
#include<cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
inline int read(){
    int X=0,w=1; char ch=0;
    while(ch<‘0‘||ch>‘9‘) {if(ch==‘-‘) w=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘) X=(X<<3)+(X<<1)+ch-‘0‘,ch=getchar();
    return X*w;
}
const int tmax=60;
int tree[400001][tmax];
int b[100001];
void build(int a,int l,int r){
    if(l==r){
      for(int i=0;i<tmax;i++){
          if(i%b[l])tree[a][i]=i+1;
          else tree[a][i]=i+2;
      }
    return;
    }
    int mid=(l+r)>>1;
    build(a*2,l,mid);
    build(a*2+1,mid+1,r);
    for(int i=0;i<tmax;i++){
      tree[a][i]=tree[a*2+1][tree[a*2][i]%tmax]+tree[a*2][i]/tmax*tmax;
    }
    return;
}
int check(int a,int l,int r,int l1,int r1,int t){
    if(l>r1||r<l1)return t;
    if(l1<=l&&r<=r1){
      return tree[a][t%tmax]+t/tmax*tmax;
    }
    int mid=(l+r)>>1;
    int k1=check(a*2,l,mid,l1,r1,t);
    int k2=check(a*2+1,mid+1,r,l1,r1,k1);
    return k2;
}
void gai(int a,int l,int r,int x,int y){
    if(x<l||r<x)return;
    if(l==x&&x==r){
      b[l]=y;
       for(int i=0;i<tmax;i++){
          if(i%b[l])tree[a][i]=i+1;
          else tree[a][i]=i+2;
      }
      return;
    }
    int mid=(l+r)>>1;
    gai(a*2,l,mid,x,y);
    gai(a*2+1,mid+1,r,x,y);
    for(int i=0;i<tmax;i++){
      tree[a][i]=tree[a*2+1][tree[a*2][i]%tmax]+tree[a*2][i]/tmax*tmax;
    }
    return;
}
int main(){
    int n=read();
    for(int i=1;i<=n;i++){
      b[i]=read();
    }
    build(1,1,n);
    int q=read();
    for(int i=1;i<=q;i++){
      char c;
      cin>>c;
      int x=read();
      int y=read();
      if(c==‘A‘){
          printf("%d\n",check(1,1,n,x,y-1,0));
      }else{
          gai(1,1,n,x,y);
      }
    }
    return 0;
}
时间: 2024-11-03 20:20:00

CF498D:Traffic Jams in the Land——题解的相关文章

CF498D Traffic Jams in the Land

嘟嘟嘟 题面:有n条公路一次连接着n + 1个城市,每一条公路有一个堵塞时刻a[i],如果当前时间能被a[i]整除,那么通过这条公路需要2分钟:否则需要1分钟. 现给出n条公路的a[i],以及m次操作.每一次操作:1.C x d:将第x条的堵塞时刻改为d.2.A x y:询问从城市x到城市y的所需时间. 这能想到是一个线段树的题,虽然做过好多道线段树的题,但遇到这种思路比较新奇的题,独立的想出来还是有一点困难. 于是稍微参照了一下题解. 我们观察一下a[i],2 <= a[i] <= 6,很小

Traffic Jams in the Land(线段树好题)

Traffic Jams in the Land CodeForces - 498D Some country consists of (n?+?1) cities, located along a straight highway. Let's number the cities with consecutive integers from 1 to n?+?1 in the order they occur along the highway. Thus, the cities are co

Codeforces 498D Traffic Jams in the Land | 线段树

题目大意: 给坐标轴1~n的点,每个点有一个权值,从一个点走到下一个点需要1s,如果当前时间是权值的倍数就要多花1s 给出q组操作,C表示单点修改权值,A表示询问0时刻x出发到y的时间 题解:因为权值只有2,3,4,5,6,所以60是一个周期,我们维护一颗线段树,维护0到59时刻出发从l到r+1用的时间 1 #include<cstdio> 2 #include<algorithm> 3 #include<cstring> 4 #define N 100010 5 us

[codeforces] 498D Traffic Jams in th Land

原题 简单的线段树问题. 对于题目中,a[i]的范围是2~6,我们仔细思考可以得出第0秒和第60秒是一样的(因为2~6的最小公倍数是60,),然后我们可以建一个线段树,里面记录0~59秒时刻开始通过这段所需要的时间.(如果一定要说这是60棵线段树也不是不可以--) #include<cstdio> #define N 100010 using namespace std; int n,a[N],q,x,y; char j; struct hhh { int l,r,dt[65]; }tre[N

UVALive-4839 HDU-3686 Traffic Real Time Query System 题解

题目大意: 有一张无向连通图,问从一条边走到另一条边必定要经过的点有几个. 思路: 先用tarjan将双连通分量都并起来,剩下的再将割点独立出来,建成一棵树,之后记录每个点到根有几个割点,再用RMQ求LCA计算. 注意:数组范围. 代码: 1 #include<cstdio> 2 #include<vector> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 const

Codeforces Round #284 (Div. 1)

A. Crazy Town 这一题只需要考虑是否经过所给的线,如果起点和终点都在其中一条线的一侧,那么很明显从起点走点终点是不需要穿过这条线的,否则则一定要经过这条线,并且步数+1.用叉积判断即可. 代码: 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<string> 5 #include<map> 6 #define N 100010 7 #def

Timus 2005. Taxi for Programmers 题解

The clock shows 11:30 PM. The sports programmers of the institute of maths and computer science have just finished their training. The exhausted students gloomily leave their computers. But there's something that cheers them up: Misha, the kind coach

ural 2020 Traffic Jam in Flower Town

2020. Traffic Jam in Flower Town Time limit: 1.0 secondMemory limit: 64 MB Having returned from Sun City, Dunno told all his friends that every shorty may have a personal automobile. Immediately after that so many citizens took a fancy of becoming ro

ZOJ Design the city LCA转RMQ

Design the city Time Limit: 1 Second      Memory Limit: 32768 KB Cerror is the mayor of city HangZhou. As you may know, the traffic system of this city is so terrible, that there are traffic jams everywhere. Now, Cerror finds out that the main reason