「省选联考2025-追忆」题解
P11831 [省选联考 2025] 追忆
pref
我常常追忆过去。
恍若昨日,却已近半年。
不再的旧日,不再的旧友。
真实的泡沫在伸手触碰的瞬间便化作虚无,连流光的幻影也不曾留下。
旧时放飞的梦想,越来越近,亦或是越来越远了。
我该在哪里停留?我问我自己。
sol
考虑分开处理连通性限制与 \(a\) 的限制。
先考虑连通性限制,这个拓扑加 bitset 处理即可,本题的图比较特殊,倒序遍历极为拓扑序。复杂度 \(O(\frac{nm}{w})\)。
考虑对 \(a\) 的限制,考虑分块,令块长为 \(S=\sqrt n\),对每个块开一个 bitset,第 \(x\) 块存储 \(\left\{i\mid a_i>(x-1)S\right\}\),也就是 \(a\) 值在块内的所有下标集合意义上的后缀和。
这样我们可以通过差分找出 \(\left\{i\mid a_i\in\left[l,r\right]\right\}\)。对于 \(l,r\) 同块的暴力修改即可,不同块的先差分整块,再暴力更新散块。单次复杂度是 \(O(\sqrt n+\frac{n}{w})\) 的。
对 \(a\) 的修改是简单的,\(O(\sqrt n)\) 暴力改 bitset 即可。
于是我们就找出了满足条件的下标,考虑如何找出这些下标内最大的 \(b\) 值。
考虑到 \(b\) 带修,我们考虑采取与 \(a\) 相同的分块方式维护。那么每次我们都只需要找到最大的与限制集合有交的块,在块内暴力跑即可。直接找是 \(O(\frac{n\sqrt n}{w})\) 的,不太优,考虑手写 bitset,然后逐个 ull 更新答案。这样答案最多被更新 \(\frac{n}{S}=\sqrt n\) 次,且 ull 的按位与操作是 \(O(1)\) 的。
最后复杂度为 \(O(\frac{(m+q)n}{w}+q\sqrt n)\)。
code
const int N=1e5+5,W=1570,w=64,S=320;
struct btst{
ull val[W];
inline void reset(){memset(val,0,sizeof val);}
inline void set(const int &x){val[x>>6]|=1ull<<(x&w-1);}
inline void flip(const int &x){val[x>>6]^=1ull<<(x&w-1);}
inline int any(const int &x){return val[x>>6]>>(x&w-1)&1;}
inline void operator&=(const btst &b){repl(i,0,W)val[i]&=b.val[i];}
inline void operator|=(const btst &b){repl(i,0,W)val[i]|=b.val[i];}
inline void operator^=(const btst &b){repl(i,0,W)val[i]^=b.val[i];}
};
int n,m,q,nn;
int a[N],b[N];
int ta[N],tb[N];
vec<int> G[N];
btst T[N],A[S],B[S],C;
inline void Main(){
read(n,m,q);
nn=(n+S-1)/S;
rep(i,1,nn)A[i].reset(),B[i].reset();
rep(i,1,n)G[i].clear(),T[i].reset();
rep(i,1,m){
int u,v;read(u,v);
G[u].pub(v);
}
per(i,n,1){
T[i].set(i);
for(auto j:G[i])T[i]|=T[j];
}
rep(i,1,n){
read(a[i]);ta[a[i]]=i;
per(j,(a[i]+S-1)/S,1)A[j].set(i);
}
rep(i,1,n){
read(b[i]);tb[b[i]]=i;
per(j,(b[i]+S-1)/S,1)B[j].set(i);
}
while(q--){
int o;read(o);
if(o==1){
int x,y;
read(x,y);
if(a[x]>a[y])swap(x,y);
int L=(a[x]+S-1)/S,R=(a[y]+S-1)/S;
rep(j,L+1,R)A[j].flip(x),A[j].flip(y);
swap(a[x],a[y]);swap(ta[a[x]],ta[a[y]]);
}else if(o==2){
int x,y;
read(x,y);
if(b[x]>b[y])swap(x,y);
int L=(b[x]+S-1)/S,R=(b[y]+S-1)/S;
rep(j,L+1,R)B[j].flip(x),B[j].flip(y);
swap(b[x],b[y]);swap(tb[b[x]],tb[b[y]]);
}else{
int x,l,r;
read(x,l,r);C.reset();
int L=(l+S-1)/S,R=(r+S-1)/S;
if(L==R){
rep(i,l,r)C.set(ta[i]);
}else{
C=A[L+1];C^=A[R];
rep(i,l,L*S)C.set(ta[i]);
rep(i,(R-1)*S+1,r)C.set(ta[i]);
}
C&=T[x];
int p=0;
repl(i,0,W)while(p+1<=nn&&C.val[i]&B[p+1].val[i])++p;
if(!p)put(0);
else{
l=(p-1)*S+1;
r=min(p*S,n);
int ans=0;
rep(i,l,r)if(C.any(tb[i]))ans=i;
put(ans);
}
}
}
}
aft
虽然说也有些小细节不是特别无脑吧,但整体来看确实是道相对简单的分块了。
曾经的日子无法重来,我只不过是一个过客。但我仍然渴望在每一次追忆之旅中留下闲暇时间,在一个场景前驻足,在岁月的朦胧里瞭望过去的自己,感受尽可能多的甜蜜。美好的时光曾流过我的身体,我便心满意足。

浙公网安备 33010602011771号