省选模拟40

A. 交通

预处理一下如果在第 \(i\) 个路口遇到红灯,然后走到结尾的时间

从后往前计算,用线段树维护一下,就能查询出最近的遇到一个红灯的位置

然后加上中间路程的时间再加上等待红灯的时间就行了

再对于每个询问都这么找一下第一个遇到的红灯就能算出答案

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define lson st[x].ls
#define rson st[x].rs
#define meow(args...) fprintf(stderr,args)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,q,g,r,T,rt,tot;
int d[50010],s[50010],f[50010];
struct seg{int ls,rs,mn;}st[50010*80];
inline void pushup(int x){
	st[x].mn=n+1;
	if(lson) st[x].mn=min(st[lson].mn,st[x].mn);
	if(rson) st[x].mn=min(st[rson].mn,st[x].mn);
}
void upd(int &x,int l,int r,int pos,int k){
	if(!x) st[x=++tot].mn=n+1;if(l==r) return st[x].mn=k,void();
	int mid=(l+r)>>1;
	if(pos<=mid) upd(lson,l,mid,pos,k);
	else upd(rson,mid+1,r,pos,k);
	pushup(x);
}
int query(int x,int l,int r,int L,int R){
	if(!x) return n+1;if(L<=l&&r<=R) return st[x].mn;
	int mid=(l+r)>>1,res=n+1;
	if(L<=mid) res=min(res,query(lson,l,mid,L,R));
	if(R>mid) res=min(res,query(rson,mid+1,r,L,R));
	return res;
}
inline int getnxt(int pos){
	int L,R,v=n+1;
	if(pos<g){
		L=g-pos;R=L+r-1;
		v=min(v,query(rt,0,T-1,L,R));
	}else{
		L=0;R=T-1-pos;
		v=min(v,query(rt,0,T-1,L,R));
		R=T-1;L=T-(pos-g);
		if(L<=R) v=min(v,query(rt,0,T-1,L,R));
	}
	return v;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("traffic.in","r",stdin);
	freopen("traffic.out","w",stdout);
	n=read(),g=read(),r=read();T=g+r;
	for(int i=1;i<=n+1;i++) d[i]=read();
	for(int i=1;i<=n+1;i++) s[i]=s[i-1]+d[i];
	for(int i=n,v;i;i--){
		v=getnxt(T-s[i]%T);
		f[i]=f[v]+s[v]-s[i];
		if(v!=n+1) f[i]+=(T-(s[v]-s[i])%T);
		upd(rt,0,T-1,s[i]%T,i);
	}
	q=read();
	for(int i=1,t,v,res;i<=q;i++){
		t=read();v=getnxt(t%T);
		res=f[v]+s[v]+t;
		if(v!=n+1) res+=(T-(s[v]+t)%T);
		printf("%lld\n",res);
	}
	return 0;
}

B. 选拔

用字符串的算法似乎不太好搞

写了个 \(AC\) 自动机,最多拿 \(90\)

于是用考虑一个 \(dp\)

\(f1_{i,j,k},f2_{i,j,k}\) 表示在第 \(i\) 个节点从下/上能匹配到第 \(j\) 个串的第 \(k\) 个字符

发现后两维总共就 \(O(s)\) 于是压到一起用 \(bitset\) 去优化

复杂度 \(O(\frac{ns}{w})\)

Code
#include<bits/stdc++.h>
#define int long long//OVERFLOW !!! MEMORY LIMIT !!!
#define rint signed
#define meow(args...) fprintf(stderr,args)
#define inf 0x3f3f3f3f3f3f3f3f
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,now;
char st[10];
string s,t[30010];
bool jud;
vector<pair<int,int>>g[30010];
bitset<60010>f1[30010],f2[30010],trans[30],tmp,ans;
void dfs(int x,int fa){
	f1[x]=f2[x]=trans[26];
	for(auto L:g[x]) if(L.first!=fa){
		dfs(L.first,x);
		f1[L.first]<<=1;f1[L.first]&=trans[L.second];
		tmp=f1[L.first];tmp<<=1;tmp&=f2[x];ans|=tmp;
		f2[L.first]>>=1;f2[L.first]&=trans[L.second];
		tmp=f1[x];tmp<<=1;tmp&=f2[L.first];ans|=tmp;
		f1[x]|=f1[L.first],f2[x]|=f2[L.first];
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("selection.in","r",stdin);
	freopen("selection.out","w",stdout);
	n=read();
	for(int i=1,x,y;i<n;i++){
		x=read(),y=read();scanf("%s",st+1);
		g[x].emplace_back(make_pair(y,st[1]-'a'));
		g[y].emplace_back(make_pair(x,st[1]-'a'));
	}
	m=read();
	for(int i=1;i<=m;i++){cin>>t[i];s=s+char('z'+1)+t[i];}s=s+char('z'+1);
	for(int i=0;i<s.length();i++) trans[s[i]-'a'][i]=1;
	dfs(1,0);now=1;
	for(int i=1;i<=m;i++){
		jud=0;
		for(int j=now;j<=now+t[i].length();j++) if(ans[j]){jud=1;break;}
		now+=t[i].length()+1;
		puts(jud?"YES":"NO");
	}
	return 0;
}

C. 等待

咕咕咕

posted @ 2022-03-29 20:10  Max_QAQ  阅读(64)  评论(0编辑  收藏  举报