• CF #284 div1 D. Traffic Jams in the Land 线段树


    大意是有n段路,每一段路有个值a,通过每一端路需要1s,如果通过这一段路时刻t为a的倍数,则需要等待1s再走,也就是需要2s通过。

    比较头疼的就是相邻两个数之间会因为数字不同制约,一开始想a的范围是2-6,处理这几个数字互相之间的关系,还是想岔了。

    正解应当是开60个线段树,因为2-6的LCM是60,也就是所有数字模2-6,结果的循环节长度为60。所以如果从i到j,开始时刻如果为0,则答案一定与开始时刻为60相同。

    第x个线段树某个节点范围如果是i和j,维护的便是开始时刻模60为x的情况下,从i到j+1需要的时间。

    写的时候按照这个处理节点信息合并与查询即可。

     1 #include <iostream>
     2 #include <vector>
     3 #include <algorithm>
     4 #include <string>
     5 #include <cstring>
     6 #include <cstdio>
     7 #include <cmath>
     8 #include <cstdlib>
     9 #include <queue>
    10 #include <stack>
    11 #include <map>
    12 #include <set>
    13 
    14 using namespace std;
    15 
    16 const int N=1e5+10;
    17 const int M=60;
    18 int v[N<<2][M];
    19 
    20 void up(int rt) {
    21     for (int i=0;i<M;i++) {
    22         v[rt][i]=v[rt<<1][i]+v[rt<<1|1][(i+v[rt<<1][i])%M];
    23     }
    24 }
    25 void build(int l,int r,int rt) {
    26     if (l==r) {
    27         int a;
    28         scanf("%d",&a);
    29         for (int i=0;i<M;i++)
    30             v[rt][i]=1+(i%a==0);
    31         return;
    32     }
    33     int m=(l+r)>>1;
    34     build(l,m,rt<<1);
    35     build(m+1,r,rt<<1|1);
    36     up(rt);
    37 }
    38 void update(int p,int a,int l,int r,int rt) {
    39     if (l==r) {
    40         for (int i=0;i<M;i++)
    41             v[rt][i]=1+(i%a==0);
    42         return;
    43     }
    44     int m=(l+r)>>1;
    45     if (p<=m)
    46         update(p,a,l,m,rt<<1);
    47     else
    48         update(p,a,m+1,r,rt<<1|1);
    49     up(rt);
    50 }
    51 int ask(int L,int R,int l,int r,int rt,int p) {
    52     if (L<=l&&r<=R) {
    53         return v[rt][p];
    54     }
    55     int ret=0;
    56     int m=(l+r)>>1;
    57     if (L<=m) ret+=ask(L,R,l,m,rt<<1,p);
    58     if (R>m) ret+=ask(L,R,m+1,r,rt<<1|1,(p+ret)%M);
    59     return ret;
    60 }
    61 int main () {
    62     int n;
    63     scanf("%d",&n);
    64     build(1,n,1);
    65     int Q;
    66     scanf("%d",&Q);
    67     while (Q--) {
    68         char s[5];
    69         int x,y;
    70         scanf("%s %d %d",s,&x,&y);
    71         if (s[0]=='C')
    72             update(x,y,1,n,1);
    73         else
    74             printf("%d
    ",ask(x,y-1,1,n,1,0));
    75     }
    76     return 0;
    77 }
  • 相关阅读:
    【模块汇总】
    【葵花宝典@2020Python面试】
    【数据库汇总】
    【Python初阶汇总】
    【葵花宝典@职场动物园】
    【2020Python修炼记】web框架之Django实战-BBS-高仿版博客园
    【2020Python修炼记】web框架之 权限管理+Auth模块
    Java SE基础2:Class类与反射 反射破坏了封装吗?
    Java SE基础1:面向对象三大基本特性
    11.堆与堆的应用
  • 原文地址:https://www.cnblogs.com/micrari/p/5178396.html
Copyright © 2020-2023  润新知