题解 交通
考虑线段树上位置 \(i\) 维护 \(t=i\) 时的答案
那么可以从后往前 DP
转移是显然的
红灯的区间赋值为下一次绿灯的答案即可
复杂度 \(O(n\log n)\)
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 100010
#define ll long long
#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, g, r, q;
int d[N];
namespace force{
void solve() {
int T=g+r;
for (int i=1,t; i<=q; ++i) {
t=read();
for (int j=1; j<=n; ++j) {
t+=d[j];
if ((t%T)>=g) t+=T-(t%T);
}
t+=d[n+1];
printf("%lld\n", t);
}
}
}
namespace task1{
int val[N], sum_d;
int gl[N], gr[N];
void upd(int l, int r, int dat) {for (int i=l; i<=r; ++i) val[i]=dat;}
int query(int i) {return val[i];}
void solve() {
int len=g+r;
int l=g, r=g+::r;
for (int i=1; i<=n+1; ++i) sum_d+=d[i];
for (int i=0; i<len; ++i) val[i]=i+sum_d;
gl[1]=g-d[1]; gr[1]=0-d[1];
gl[1]=(gl[1]%len+len)%len, gr[1]=(gr[1]%len+len)%len;
for (int i=2; i<=n; ++i) gl[i]=((gl[i-1]-d[i])%len+len)%len, gr[i]=((gr[i-1]-d[i])%len+len)%len;
for (int i=n; i; --i) {
// cout<<"i: "<<i<<endl;
int l=gl[i], r=gr[i];
if (l<r) upd(l, r-1, query(r));
else {
upd(l, len-1, query(r)+len);
if (r) upd(0, r-1, query(r));
}
l+=d[i]; r+=d[i];
}
for (int i=1,t; i<=q; ++i) {
t=read();
printf("%lld\n", len*(t/len)+query(t%len));
}
}
}
namespace task2{
int gl[N], gr[N], sum_d;
int rot, lson[N*145], rson[N*145], val[N*145], tag[N*145], tot;
#define ls(p) lson[p]
#define rs(p) rson[p]
#define tag(p) tag[p]
#define val(p) val[p]
void spread(int p) {
if (tag(p)==-1) return ;
if (!ls(p)) ls(p)=++tot, val(ls(p))=tag(ls(p))=-1;
if (!rs(p)) rs(p)=++tot, val(rs(p))=tag(rs(p))=-1;
val(ls(p))=tag(ls(p))=tag(p);
val(rs(p))=tag(rs(p))=tag(p);
tag(p)=-1;
}
void upd(int& p, int tl, int tr, int ql, int qr, int dat) {
if (!p) p=++tot, ls(p)=rs(p)=0, val(p)=tag(p)=-1;
if (ql<=tl&&qr>=tr) {val(p)=tag(p)=dat; return ;}
spread(p);
int mid=(tl+tr)>>1;
if (ql<=mid) upd(ls(p), tl, mid, ql, qr, dat);
if (qr>mid) upd(rs(p), mid+1, tr, ql, qr, dat);
}
int query(int p, int tl, int tr, int pos) {
if (!p) return pos+sum_d;
if (tl==tr) return val(p)==-1?pos+sum_d:val(p);
spread(p);
int mid=(tl+tr)>>1;
if (pos<=mid) return query(ls(p), tl, mid, pos);
else return query(rs(p), mid+1, tr, pos);
}
void solve() {
// cerr<<double(sizeof(lson)*4)/1000/1000<<endl;
int len=g+r;
for (int i=1; i<=n+1; ++i) sum_d+=d[i];
gl[1]=g-d[1]; gr[1]=0-d[1];
gl[1]=(gl[1]%len+len)%len, gr[1]=(gr[1]%len+len)%len;
for (int i=2; i<=n; ++i) gl[i]=((gl[i-1]-d[i])%len+len)%len, gr[i]=((gr[i-1]-d[i])%len+len)%len;
for (int i=n; i; --i) {
// cout<<"i: "<<i<<endl;
int l=gl[i], r=gr[i];
if (l<r) upd(rot, 0, len, l, r-1, query(rot, 0, len, r));
else {
int t=query(rot, 0, len, r);
upd(rot, 0, len, l, len-1, t+len);
if (r) upd(rot, 0, len, 0, r-1, t);
}
l+=d[i]; r+=d[i];
}
for (int i=1,t; i<=q; ++i) {
t=read();
printf("%lld\n", len*(t/len)+query(rot, 0, len, t%len));
}
// cerr<<"tot: "<<tot<<endl;
}
}
signed main()
{
freopen("traffic.in", "r", stdin);
freopen("traffic.out", "w", stdout);
n=read(); g=read(); r=read();
for (int i=1; i<=n+1; ++i) d[i]=read();
q=read();
// force::solve();
// task1::solve();
task2::solve();
return 0;
}