1. 程式人生 > >[codeforces] 498D Traffic Jams in th Land

[codeforces] 498D Traffic Jams in th Land

source 得出 我們 blog pro using i++ ams ret

原題

簡單的線段樹問題。

對於題目中,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*4];

int read()
{
    int ans=0,fu=1;
    char j=getchar();
    for
(;(j<‘0‘ || j>‘9‘) && j!=‘-‘;j=getchar()) ; if (j==‘-‘) fu=-1; for (;j>=‘0‘ && j<=‘9‘;j=getchar()) ans*=10,ans+=j-‘0‘; return ans*fu; } void build(int i,int l,int r) { tre[i].l=l; tre[i].r=r; if (l==r) { for (int t=0;t<60;t++) if (!t || t%a[l]==0
) tre[i].dt[t]=2; else tre[i].dt[t]=1; return ; } int mid=(l+r)>>1; build(i*2,l,mid); build(i*2+1,mid+1,r); for (int t=0;t<60;t++) tre[i].dt[t]=tre[i*2].dt[t]+tre[i*2+1].dt[(t+tre[i*2].dt[t])%60]; } void modify(int i,int x) { if (tre[i].l==tre[i].r && x==tre[i].l) { for
(int t=0;t<60;t++) if (t%a[x]==0) tre[i].dt[t]=2; else tre[i].dt[t]=1; return ; } int mid=(tre[i].l+tre[i].r)>>1; if (x<=mid) modify(i*2,x); else modify(i*2+1,x); for (int t=0;t<60;t++) tre[i].dt[t]=tre[i*2].dt[t]+tre[i*2+1].dt[(t+tre[i*2].dt[t])%60]; } int query(int i,int l,int r,int t) { if (tre[i].l==l && tre[i].r==r) return tre[i].dt[t%60]; int mid=(tre[i].l+tre[i].r)>>1; if (r<=mid) return query(i*2,l,r,t); if (l>mid) return query(i*2+1,l,r,t); else { int p=query(i*2,l,mid,t); p+=query(i*2+1,mid+1,r,(t+p)%60); return p; } } int main() { n=read(); for (int i=1;i<=n;i++) a[i]=read(); build(1,1,n); q=read(); while (q--) { j=getchar(); x=read(); y=read(); if (j==‘C‘) a[x]=y,modify(1,x); else printf("%d\n",query(1,x,y-1,0)); } return 0; }

[codeforces] 498D Traffic Jams in th Land