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 using namespace std;
 6 struct node
 7 {
 8     int l,r,tim[65];
 9 }t[4*N];
10 int n,q,a[N],x,y;
11 char s[N];
12 void pushup(int p)
13 {
14     for (int i=0;i<60;i++)
15     t[p].tim[i]=t[2*p].tim[i]+t[2*p+1].tim[(t[2*p].tim[i]+i)%60];
16 }
17 void build(int p,int l,int r)
18 {
19     t[p].l=l,t[p].r=r;
20     if (l!=r)
21     {
22     int mid=l+r>>1;
23     build(2*p,l,mid);
24     build(2*p+1,mid+1,r);
25     pushup(p);
26     }
27     else
28     for (int i=0;i<60;i++)
29         t[p].tim[i]=1+!(i%a[l]);
30 }
31 void modify(int p,int l,int k)
32 {
33     int ll=t[p].l,rr=t[p].r,mid=ll+rr>>1;
34     if (ll==l && ll==rr)
35     {
36     for (int i=0;i<60;i++)
37         t[p].tim[i]=1+!(i%k);
38     return;
39     }
40     if (l<=mid) modify(2*p,l,k);
41     else modify(2*p+1,l,k);
42     pushup(p);
43 }
44 int query(int p,int x,int y,int ti)
45 {
46     int ll=t[p].l,rr=t[p].r,mid=ll+rr>>1;
47     if (x==ll && y==rr)
48     return t[p].tim[ti%60];
49     if (y<=mid)
50     return query(2*p,x,y,ti);
51     if (x>mid) return query(2*p+1,x,y,ti);
52     int tmp=query(2*p,x,mid,ti);
53     return tmp+query(2*p+1,mid+1,y,(ti+tmp)%60);
54 }
55 int main()
56 {
57     scanf("%d",&n);
58     for (int i=1;i<=n;i++)
59     scanf("%d",a+i);
60     a[n+1]=1;
61     build(1,1,n+1);
62     scanf("%d",&q);
63     while (q--)
64     {
65     scanf("%s",s);
66     scanf("%d%d",&x,&y);
67     if (s[0]==‘C‘)
68         modify(1,x,y);
69     else
70         printf("%d\n",query(1,x,y-1,0));
71     }
72     return 0;
73 }
时间: 2024-10-11 19:55:10

Codeforces 498D Traffic Jams in the Land | 线段树的相关文章

[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

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 52C Circular RMQ(区间循环线段树,区间更新,区间求和)

转载请注明出处:http://blog.csdn.net/u012860063 题目链接:http://codeforces.com/problemset/problem/52/C You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segm

codeforces 446C DZY Loves Fibonacci Numbers 数论+线段树成段更新

DZY Loves Fibonacci Numbers Time Limit:4000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Submit Status Appoint description:  System Crawler  (2014-07-14) Description In mathematical terms, the sequence Fn of Fibonacci numbers is defi

Codeforces Beta Round #12 D. Ball (线段树)

题目大意: n个女性中,如果有一个女性的三维比这个女性的三维都大,这个女性就要自杀.问要自杀多少个. 思路分析: 先按照第一维排序. 然后离散化第二维,用第二维的下标建树,树上的值是第三维,更新的时候取最大值. 注意是按照第一维度从大到小进入线段树. 而且还要严格递增. 所以处理第一维度比较大小的时候要分开处理,要把相同的先判断,再更新入树. 那么如何判断这个女性是否自杀. 首先,你知道第一维度是从大到小的,所以先进树了的节点的第一维度一定更大. 再次,我们考虑第二维度,我们去树上第二维度下标大

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),一些

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,很小

Educational Codeforces Round 23 F. MEX Queries(线段树)

题目链接:Educational Codeforces Round 23 F. MEX Queries 题意: 一共有n个操作. 1.  将[l,r]区间的数标记为1. 2.  将[l,r]区间的数标记为0. 3.  将[l,r]区间取反. 对每个操作,输出标记为0的最小正整数. 题解: hash后,用线段树xjb标记一下就行了. 1 #include<bits/stdc++.h> 2 #define ls l,m,rt<<1 3 #define rs m+1,r,rt<&l

Codeforces 484E Sign on Fence(可持久化线段树+二分)

题目链接:Codeforces 484E Sign on Fence 题目大意:给定给一个序列,每个位置有一个值,表示高度,现在有若干查询,每次查询l,r,w,表示在区间l,r中, 连续最长长度大于w的最大高度为多少. 解题思路:可持久化线段树维护区间合并,前端时间碰到一题可持久化字典树,就去查了一下相关论文,大概知道了是 什么东西. 将高度按照从大到小的顺序排序,然后每次插入一个位置,线段树维护最长连续区间,因为插入是按照从大到小的顺 序,所以每次的线段树中的连续最大长度都是满足高度大于等于当