码迷,mamicode.com
首页 > 其他好文 > 详细

CF 498D 线段树

时间:2016-02-02 20:40:09      阅读:313      评论:0      收藏:0      [点我收藏+]

标签:

大意是有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\n",ask(x,y-1,1,n,1,0));
75     }
76     return 0;
77 }

 

CF 498D 线段树

标签:

原文地址:http://www.cnblogs.com/micrari/p/5178396.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!