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,很小,而且这些数的最小公倍数最大只有60,那么对于每一个节点,我们开一个tim[60]的数组,tim[j]维护在时刻 j ,通过这段区间需要的时间。

那么区间合并的时候就是 j 从0~59枚举,这个区间的第 j 个时刻花费的时间等于左区间的从 j 时刻花费的时间x,加上右区间从j + x时刻花费的时间。于是这题就完事啦。

时间复杂度O(mlogn * 60)。

  1 #include<cstdio>
  2 #include<iostream>
  3 #include<cmath>
  4 #include<algorithm>
  5 #include<cstring>
  6 #include<cstdlib>
  7 #include<cctype>
  8 #include<vector>
  9 #include<stack>
 10 #include<queue>
 11 using namespace std;
 12 #define enter puts("") 
 13 #define space putchar(' ')
 14 #define Mem(a, x) memset(a, x, sizeof(a))
 15 #define rg register
 16 typedef long long ll;
 17 typedef double db;
 18 const int INF = 0x3f3f3f3f;
 19 const db eps = 1e-8;
 20 const int maxn = 1e5 + 5;
 21 inline ll read()
 22 {
 23   ll ans = 0;
 24   char ch = getchar(), last = ' ';
 25   while(!isdigit(ch)) {last = ch; ch = getchar();}
 26   while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();}
 27   if(last == '-') ans = -ans;
 28   return ans;
 29 }
 30 inline void write(ll x)
 31 {
 32   if(x < 0) x = -x, putchar('-');
 33   if(x >= 10) write(x / 10);
 34   putchar(x % 10 + '0');
 35 }
 36 
 37 int n, m;
 38 char s[2];
 39 
 40 struct Tree
 41 {
 42     int l, r;
 43     int tim[65];
 44 }t[maxn << 2];
 45 void pushup(int now)
 46 {
 47     for(int i = 0; i < 60; ++i)
 48         t[now].tim[i] = t[now << 1].tim[i] + t[now << 1 | 1].tim[(i + t[now << 1].tim[i]) % 60];
 49 }
 50 void build(int L, int R, int now)
 51 {
 52     t[now].l = L; t[now].r = R;
 53     if(L == R)
 54     {
 55         int x = read();
 56         for(int i = 0; i < 60; ++i)
 57             if(!(i % x)) t[now].tim[i] = 2;
 58             else t[now].tim[i] = 1;
 59         return;
 60     }
 61     int mid = (L + R) >> 1;
 62     build(L, mid, now << 1);
 63     build(mid + 1, R, now << 1 | 1);
 64     pushup(now);
 65 }
 66 void update(int idx, int d, int now)
 67 {
 68     if(t[now].l == t[now].r)
 69     {
 70         for(int i = 0; i < 60; ++i)
 71             if(!(i % d)) t[now].tim[i] = 2;
 72             else t[now].tim[i] = 1;        
 73         return;
 74     }
 75     int mid = (t[now].l + t[now].r) >> 1;
 76     if(idx <= mid) update(idx, d, now << 1);
 77     else update(idx, d, now << 1 | 1);
 78     pushup(now);
 79 }
 80 int query(int L, int R, int now, int Tim)
 81 {
 82     if(t[now].l == L && t[now].r == R) return t[now].tim[Tim % 60];
 83     int mid = (t[now].l + t[now].r) >> 1;
 84     if(R <= mid) return query(L, R, now << 1, Tim);
 85     else if(L > mid) return query(L, R, now << 1 | 1, Tim);
 86     else 
 87     {
 88         int ret = query(L, mid, now << 1, Tim);
 89         ret += query(mid + 1, R, now << 1 | 1, (Tim + ret) % 60);
 90         return ret;
 91     }
 92 }
 93 
 94 int main()
 95 {
 96     n = read();
 97     build(1, n, 1);
 98     m = read();
 99     for(int i = 1; i <= m; ++i)
100     {
101         scanf("%s", s);
102           if(s[0] == 'C')
103         {
104               int x = read(), d = read();
105               update(x, d, 1);
106         }
107           else
108         {
109               int L = read(), R = read();
110               write(query(L, R - 1, 1, 0)); enter;    //别忘 R - 1 
111         }
112     }
113   return 0;
114 }
View Code
原文地址:https://www.cnblogs.com/mrclr/p/9784569.html