CF187D BRT Contract

考虑如果哪次经过了红灯则显然已经和出发的时间没关系了。
然后我们需要做的是怎么样找到最近的一个是红灯的点。
然后实际下是我们做一个前缀和:\(L_i = \sum d_i\)
然后求\(\min (L_y - L_i) \mod (g + r) > g\)
然后在值域上动态开点线段树,区间查询\(min\)即可。
倒过来处理一下。

//code by fhq_treap
#include<iostream>
#include<cstdio>
#define ll long long 
#define N 100005

int n,g,r;
int mod;
ll d[N],f[N];

struct P{
	int L,R;
	ll mn;
	P(){mn = 1e18;}
}T[N * 60];

int cnt;

#define mid ((l + r) >> 1)
#define ls(x) T[x].L
#define rs(x) T[x].R

int Root;

inline void up(int u){T[u].mn = std::min(T[ls(u)].mn,T[rs(u)].mn);}

inline void change(int &u,int l,int r,int p,int v){
	if(!u)u = ++cnt;
//	std::cout<<u<<" "<<l<<" "<<r<<" "<<p<<" "<<v<<std::endl;	
	if(l == r){
		T[u].mn = v;
		return ;
	}
	if(p <= mid)
	change(ls(u),l,mid,p,v);
	else
	change(rs(u),mid + 1,r,p,v);
	up(u);
}

inline ll query(int u,int l,int r,int tl,int tr){
//	std::cout<<u<<" "<<l<<" "<<r<<" "<<tl<<" "<<tr<<std::endl;
	if(tl > tr)return 1e18;
	if(!u)return 1e18;
	if(tl <= l && r <= tr)return T[u].mn;
	ll ans = 1e18;
	if(tl <= mid)ans = std::min(ans,query(ls(u),l,mid,tl,tr));
	if(tr > mid)ans = std::min(ans,query(rs(u),mid + 1,r,tl,tr));
	return ans;	
}

#define root Root,0,mod - 1

int q;

int main(){
	scanf("%d%d%d",&n,&g,&r);
	mod = g + r;
	for(int i = 1;i <= n + 1;++i)
	scanf("%lld",&d[i]),d[i] = d[i - 1] + d[i];
	for(int i = n;i;-- i){
		int t = mod - d[i] % mod;
		ll nex = 1e18;
		nex = std::min(nex,query(root,std::max(0,g - t),mod - 1 - t));
		if(g - t < 0)
		nex = std::min(nex,query(root,g - t + mod,mod - 1));
		if(nex != 1e18)
		f[i] = d[nex] - d[i] + (mod - (d[nex] - d[i]) % mod) + f[nex];
		else
		f[i] = d[n + 1] - d[i];
		change(root,d[i] % mod,i);
	}
	scanf("%d",&q);
	int las = 0;
	while(q -- ){
		int t;
		scanf("%d",&t);
		t = t ^ las;
		int tt = t % mod;
		ll nex = 1e18;
		nex = std::min(nex,query(root,std::max(0,g - tt),mod - 1 - tt));
		if(g - tt < 0)
		nex = std::min(nex,query(root,g - tt + mod,mod - 1));
//		std::cout<<nex<<std::endl;
		if(nex == 1e18)
		std::cout<<t + d[n + 1]<<std::endl,las = (t + d[n + 1]) % 2147483647;
		else
		std::cout<<d[nex] + (mod - (d[nex] + t) % mod) + f[nex] + t<<std::endl,las = (d[nex] + (mod - (d[nex] + t) % mod) + f[nex] + t) % 2147483647;
	}
}
posted @ 2021-10-28 15:05  fhq_treap  阅读(97)  评论(0编辑  收藏  举报