20240917【省选】模拟
难说
T1
暴力可以写dp
只要你学过线性基那么你就会想怎么用线性基做,显然是要套点数据结构维护的。你要知道两个线性基可以在 的时间内合并,得到的线性基是原来两个的交。可以用线段树维护,复杂度 ,难说能不能过。
没有修改,所以考虑用常熟小一点的数据结构,可以用ST表维护最值,复杂度 ,小了一点。
发现瓶颈在于 的合并,看能不能优化成一个老哥。一个简单的思路是分治,把询问离线下来,处理跨过中点的询问,就只会对线性基产生 次的修改,复杂度被优化成 ,好像能过了。
然后是正解,看不懂:
啥都能扫描线(
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll int
#define in inline
const ll N=1145140,M=1919810,inf=2e9,V=29;
ll n,Q,a[N],f[N],p[N],x;
ll ans[N];
struct xx{
ll l,r,d,id;
}q[N];
bool cmp(xx x,xx y){
return x.r<y.r;
}
bool flag;
void insert(ll x,ll id){
for(ll i=V;i>=0;--i)
if(x&(1ll<<i)){
if(!f[i]){
f[i]=x,p[i]=id;
return;
}
else{
if(id>p[i]){
swap(id,p[i]);
swap(x,f[i]);
}
x^=f[i];
}
}
flag=1;
}
ll qmax(ll d,ll l){
for(int i=V;i>=0;--i)
if(p[i]>=l) d=max(d,d^f[i]);
return d;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
n=read();
for(int i=1;i<=n;++i) a[i]=read();
Q=read();
for(int i=1;i<=Q;++i) q[i].l=read(),q[i].r=read(),q[i].d=read(),q[i].id=i;
//cin>>q[i].l>>q[i].r>>q[i].d,q[i].id=i;
sort(q+1,q+Q+1,cmp);
for(int i=1,j=1;i<=Q;++i){
while(j<=q[i].r){
insert(a[j],j);
++j;
}
ans[q[i].id]=qmax(q[i].d,q[i].l);
}
for(int i=1;i<=Q;++i) write(ans[i]),putchar('\n');
return 0;
}
T2
应该冲正解的,这个题其实真的挺简单的,就是建图。你会发现一个点能早到就尽量早到,不会因为可能错开车而使得时间不优。注意不需要在不同线路之间建边。
对每条线路把这个环建出来,每天边要记录 在线路中的下标(从 开始)和线路的长度用于计算到达时间。用 dij和SPFA 都行,但松弛过程中边权是根据 在线路中的位置和 确定的,具体看代码,很容易手推出来。
点击查看代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define eb emplace_back
#define pi pair<ll,ll>
const ll N=2*114514,M=1919810,inf=1e18;
ll n,m,t[N];
struct xx{
ll v,t,le;
};
ll dis[N];
bool vis[N];
vector <xx> g[N];
priority_queue <pi,vector<pi>,greater<pi>> q;
void dij(){
memset(dis,63,sizeof(dis));
dis[1]=0,q.push({dis[1],1});
while(!q.empty()){
ll u=q.top().second; q.pop();
if(vis[u]) continue;
vis[u]=1;
for(xx x:g[u]){
ll v=x.v,t=x.t,le=x.le,w=0;
if(dis[u]%le<=t) w=t-dis[u]%le+1;
else w=le-dis[u]%le+t+1;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push({dis[v],v});
}
}
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
cin>>n>>m;
for(int i=1;i<=m;++i){
cin>>t[i];
vector <ll> a;
for(int j=1,x;j<=t[i];++j) cin>>x,a.eb(x);
for(int j=0;j<t[i];++j) g[a[j]].eb((xx){a[(j+1)%t[i]],j,t[i]});
}
dij();
for(int i=2;i<=n;++i)
if(dis[i]==dis[0]) cout<<"-1 ";
else cout<<dis[i]<<" ";
return 0;
}
T3
智慧题。但是本来是把结论都推出来了,39pts的代码也打出来了,但是连犯两个最低级的错误,然后就没了。
不会。
頑張って