498D - Traffic Jams in the Land
Solution:
This problem abuses segment tree so bad :)
The idea is to build 60 (which is gcd of 2,3,4,5,6) segment trees, each segment tree i answers the particular query: what is the time needed to pass through roads in [L..R] given that I start at time T = i mod 60. As such, we can serve all queries in \(O(N\lg{N})\) time. The hardest part is of course to implement the trees (or plant the forest).
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cassert> using namespace std; int segtree[400005][60]; int vis[400005][60]; int a[100005]; int N, Q; int iter; int build(int p, int t, int L, int R){ if(vis[p][t%60]) return segtree[p][t%60]; vis[p][t%60] = 1; if(L==R){ segtree[p][t%60] = 1; if(t%a[L] == 0) segtree[p][t%60]++; return segtree[p][t%60]; } int M = (L+R)/2; int left = build(2*p,t,L,M); int right = build(2*p+1,t+left,M+1,R); segtree[p][t%60] = left+right; build(2*p+1,t,M+1,R); return left+right; } int rmq(int p,int t,int L,int R,int S,int T){ if(T<L||R<S)return t; if(S<=L&&R<=T){ return t + segtree[p][t%60]; } int M=(L+R)/2; int left = rmq(2*p,t,L,M,S,T); int right = rmq(2*p+1,left,M+1,R,S,T); return right; } void update(int p, int L, int R, int S){ if(R<S||S<L)return; if(R==L && L==S){ for(int i=0;i<60;++i){ segtree[p][i] = (i%a[L]==0 ? 2: 1); } return; } int M=(L+R)/2; update(2*p,L,M,S); update(2*p+1,M+1,R,S); for(int i=0;i<60;++i){ int left = segtree[2*p][i]; segtree[p][i] = segtree[2*p][i] + segtree[2*p+1][(i+left)%60]; } } int main(){ int x,y; char c; scanf("%d", &N); for(int i=0;i<N;++i){ scanf("%d", &a[i]); } for(int i=0;i<60;++i){ build(1,i,0,N-1); } scanf("%d",&Q); iter = 1; for(int qq=0;qq<Q;++qq){ scanf(" %c%d%d", &c,&x,&y); if(c=='C'){ a[x-1]=y; update(1,0,N-1,x-1); } else { printf("%d\n",rmq(1,0,0,N-1,x-1,y-2)); } } return 0; }
No comments:
Post a Comment