题解 交通

传送门

考虑线段树上位置 \(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;
}
posted @ 2022-03-29 14:26  Administrator-09  阅读(2)  评论(0编辑  收藏  举报