JZOJ5597.红绿灯

6 篇文章 0 订阅
5 篇文章 0 订阅

Description:

Input:

Output:

Sample Input:

Sample Output:

Data Constraint:

Solution:

30%数据:
按照题意直接模拟即可,设当前走的时间为 x ,若(x+di) % (g+r)>=g 则在第i个路口遇到红灯。复杂度为 O(nq)

50%数据:
观察题目考虑,在每个路口是否遇到红灯,跟已走时间对 g+r 取模有关。进一步考虑,走的时间取决于开始的时间,所以除去开始时间,每个询问所遇到的红灯,其实跟 g+r 取模后遇到的红灯相同。那么可以解决 g+r 较小的情况,即 g,r<=100 ,对于 g+r 里每一个起始点暴力预处理就好了, O(1) 回答询问,复杂度 O(n(g+r)+q)

100%数据:
既然是否遇到红灯与取模相关,那么我们尝试化出式子:设当前走过时间为 x ,若当前路口遇到红灯,那么就要加上g+rx% (g+r) ,那么到下一个路口对 g+r 取模的情况就是

(x+g+rxmod(g+r)+di)mod(g+r)

将式子化简可得:
dimod(g+r)

这提醒我们,若遇到了一个红灯,那么它相当于从这个路口第 0 秒开始向终点走去,考虑所有询问遇到了第一个红灯后,都会变成从第0秒开始,问题具有了共性,我们可以采取预处理的办法,找到从起点开始遇到的第一个红灯,将该段距离和加上预处理的答案就可以算出来。预处理出一个数组 fi ,表示从第 i 个路口向终点走去需要的时间,这个采取倒推法,具体推法跟处理询问的方式一样: 找到从i开始遇到的第一个红灯,由于是第一个红灯,那么在其之前都走过的是绿灯,也就是处理出 di 的前缀和数组 Sumi ,找到一个 j ,使得
(SumjSumi)mod(g+r)[g,g+r)

那么我们采用权值线段树维护每一个前缀和出现的最小路口编号,就可以在权值线段树上查找第一个遇到红灯的路口了,设找到的路口为 k ,则fi=SumkSumi+fk+g+r(SumkSumi)mod(g+r)。注意有可能不经过红灯,那么直接取到终点的距离就好。

最后就是询问了:对于询问的处理方式其实类似于 fi 的处理方式,甚至得到答案的式子都跟 fi 的转移类似。只不过将前缀和换成了一个关于初值 ti 的查询,具体不讲了,通过上面的推理,读者应该能够自行解决,那么这题就完美解决了,还要注意一下离散化。复杂度 O((n+q)logn)

Code:

50%数据:

# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
const int N = 1e5 + 5;
typedef long long ll;
ll d[N],ans[N];
ll r,g;
int n,q;
int main()
{
    freopen("light.in","r",stdin);
    freopen("light.out","w",stdout);
    scanf("%d%lld%lld",&n,&g,&r);
    for (int i = 1 ; i <= n + 1 ; ++i) scanf("%lld",d + i);
    scanf("%d",&q);
    if (g <= 100 && r <= 100)
    {
        for (int i = 0 ; i < g + r ; ++i)
        {
            ans[i] = i;
            for (int j = 1 ; j <= n ; ++j)
            {
                ans[i] += d[j];
                if (ans[i] % (g + r) >= g) ans[i] += (g + r) - ans[i] % (g + r);    
            }
            ans[i] += d[n + 1] - i;
        }
        while (q--)
        {
            ll x; scanf("%lld",&x);
            printf("%lld\n",x + ans[x % (g + r)]);
        }
    }else
    {
        while (q--)
        {
            ll x; scanf("%lld",&x);
            for (int i = 1 ; i <= n ; ++i)
            {
                x += d[i];
                if (x % (g + r) >= g) x += (g + r) - x % (g + r);   
            }
            printf("%lld\n",x + d[n + 1]);
        }
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}

100%数据:

# include<cstdio>
# include<cstring>
# include<algorithm>
using namespace std;
typedef long long ll;
const int N = 5e4 + 5;
const int inf = 0x3f3f3f3f;
int ls[N << 1],rs[N << 1],val[N << 1];
ll d[N],f[N],sum[N],b[N],c[N];
ll g,r;
int n,q,rt,cnt,m;
inline void ins(int &x,int l,int r,int pos,int w)
{
    if (!x) x = ++cnt;
    if (l == r) { val[x] = min(val[x],w); return; }
    int mid = (l + r) >> 1;
    if (pos <= mid) ins(ls[x],l,mid,pos,w);
    else ins(rs[x],mid + 1,r,pos,w);
    val[x] = min(val[ls[x]],val[rs[x]]);
}
inline int qry(int x,int l,int r,int l1,int r1)
{
    if (!x || l1 > r1) return inf;
    if (l >= l1 && r <= r1) return val[x];
    ll mid = (l + r) >> 1; int ret = inf;
    if (l1 <= mid) ret = qry(ls[x],l,mid,l1,r1);
    if (r1 > mid) ret = min(ret,qry(rs[x],mid + 1,r,l1,r1));
    return ret;
}
int main()
{
    freopen("light.in","r",stdin);
    freopen("light.out","w",stdout);
    memset(val,0x3f,sizeof(val));
    scanf("%d%lld%lld",&n,&g,&r);
    for (int i = 1 ; i <= n + 1 ; ++i) scanf("%lld",d + i);
    for (int i = 1 ; i <= n + 1 ; ++i) sum[i] = sum[i - 1] + d[i],c[i] = b[i] = sum[i] % (g + r);
    c[n + 2] = 0,c[n + 3] = g + r;
    sort(c + 1,c + n + 4);
    m = unique(c + 1,c + n + 4) - c - 1;
    for (int i = n ; i >= 1 ; --i)
    {
        int p;
        ll lc = (b[i] + g) % (g + r),rc = (g + r - 1 + b[i]) % (g + r);
        int l1 = lower_bound(c + 1,c + m + 1,lc) - c;
        int r1 = upper_bound(c + 1,c + m + 1,rc) - c - 1;
        if (lc <= rc) p = qry(rt,1,m,l1,r1);
        else p = min(qry(rt,1,m,l1,m),qry(rt,1,m,1,r1));
        if (p < inf) f[i] = sum[p] - sum[i] + g + r - (sum[p] - sum[i]) % (g + r) + f[p];
        else f[i] = sum[n + 1] - sum[i];
        ins(rt,1,m,lower_bound(c + 1,c + m + 1,b[i]) - c,i);
    }
    scanf("%d",&q);
    while (q--)
    {
        ll t,y; int p;
        scanf("%lld",&t); y = (g + r - t % (g + r)) % (g + r);
        ll lc = (y + g) % (g + r),rc = (g + r - 1 + y) % (g + r);
        int l1 = lower_bound(c + 1,c + m + 1,lc) - c;
        int r1 = upper_bound(c + 1,c + m + 1,rc) - c - 1;
        if (lc <= rc) p = qry(rt,1,m,l1,r1);
        else p = min(qry(rt,1,m,l1,m),qry(rt,1,m,1,r1));
        if (p < inf) printf("%lld\n",sum[p] + f[p] + g + r - (sum[p] + t) % (g + r) + t);
        else printf("%lld\n",sum[n + 1] + t);
    }
    fclose(stdin);
    fclose(stdout);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个满足要求的红绿灯示例,使用 HTML、CSS 和 JavaScript 编写。 HTML 代码: ``` <p>交通灯状态:<span id="traffic-light-status">默认</span></p> <div class="traffic-light"> <div id="red-light" class="light"></div> <div id="yellow-light" class="light"></div> <div id="green-light" class="light"></div> </div> <button onclick="changeLights()">切换状态</button> ``` CSS 代码: ``` .traffic-light { display: inline-block; position: relative; width: 60px; height: 140px; margin-right: 10px; } .light { position: absolute; width: 40px; height: 40px; border-radius: 50%; top: 10px; left: 10px; background-color: #d9d9d9; box-shadow: 0 0 0 10px rgba(0, 0, 0, 0.1) inset; } #red-light { background-color: #f00; } #yellow-light { top: 60px; background-color: #ff0; } #green-light { top: 110px; background-color: #0f0; } #traffic-light-status { font-weight: bold; font-size: 16px; } ``` JavaScript 代码: ``` var trafficLightStatus = document.getElementById('traffic-light-status'); var redLight = document.getElementById('red-light'); var yellowLight = document.getElementById('yellow-light'); var greenLight = document.getElementById('green-light'); function changeLights() { if (redLight.style.backgroundColor === 'rgb(255, 0, 0)') { redLight.style.backgroundColor = '#d9d9d9'; yellowLight.style.backgroundColor = '#d9d9d9'; greenLight.style.backgroundColor = '#0f0'; trafficLightStatus.textContent = '绿灯'; } else if (yellowLight.style.backgroundColor === 'rgb(255, 255, 0)') { redLight.style.backgroundColor = '#f00'; yellowLight.style.backgroundColor = '#d9d9d9'; greenLight.style.backgroundColor = '#d9d9d9'; trafficLightStatus.textContent = '红灯'; } else { redLight.style.backgroundColor = '#d9d9d9'; yellowLight.style.backgroundColor = '#ff0'; greenLight.style.backgroundColor = '#d9d9d9'; trafficLightStatus.textContent = '黄灯'; } } ``` 这段代码创建了一个 `div` 元素作为交通信号灯,包含三个子元素,分别代表红、黄、绿三个信号灯。同时,还创建了一个按钮,用于切换信号灯的状态。`p` 元素中的 `span` 元素用于显示当前交通灯的状态。 CSS 中设置了默认状态的颜色为灰色,同时使用了 `box-shadow` 属性来实现外圈的效果。 JavaScript 中通过获取三个信号灯的 DOM 元素,然后通过判断当前颜色来切换信号灯的状态。同时,也更新了页面上的交通灯状态文字。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值