1. 程式人生 > >CF498D:Traffic Jams in the Land——題解

CF498D:Traffic Jams in the Land——題解

連接 urn som types force pin 駕駛員 是不是 names

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
10
2 5 3 2 3 5 3 4 2 4
10
C 10 6
A 2 6
A 1 3
C 3 4
A 3 11
A 4 9
A 5 6
C 7 3
A 8 10
A 2 5
Output
5
3
14
6
2
4
4

這道題還是不是那麽好想的……

我們需要發現一個性質:對於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;
}

CF498D:Traffic Jams in the Land——題解