[省选联考 2025] 追忆 题解
[省选联考 2025] 追忆 题解
小丑来改省选题了
首先发现问题不弱于求导出子图,复杂度大概就是 \(O(\dfrac{n^2}{w})\) 的样子
一
先说一个大常熟做法,胜在简单
考虑特殊性质
容易发现性质C看起来就非常可做,去掉了 \(l,r\) 的限制使得我们拥有足够的复杂度去做后面的东西
考虑对操作分块:先bitset预处理出一个点可达的所有点,把修改全当成赋值,对于块内的查询直接暴力查看是否有贡献就好了,然后将所有修改位置置为 \(0\),在dag 上跑一遍 dp 即可得到答案,复杂度显然是 \(O(\dfrac{n^2}{w}+n\sqrt n)\)
我们看看这个做法还能不能拿到更高的分
后面的东西里面都有区间,尝试对 \(a\) 进行分块,重构的时候每次求出连续的一段 \(a\) 对当前点的贡献
如果暴力做这个东西的话会比刚才多个块数(要跑块数遍)复杂度是 \(O((n+m)\dfrac{n}{B1}\dfrac{q}{B2}+q(\dfrac{n}{B1}+B1+B2)))\) 的
因为 \(n,m,q\) 同阶,把柿子写好看点就得到了 \(O((\dfrac{n^3}{B1B2}+\dfrac{n^2}{B1}+nB1+nB2)))\) 的
容易发现只要取 \(B1=B2=n^\frac{2}{3}\) 即可获得 \(O(\dfrac{n^2}{w}+n^\frac{5}{3})\) 的复杂度,算出来应该是可以通过的,不过可能需要卡常,期望得分 \(88\sim 100\)
但是我场上以为这个东西是 \(O(n^2)\) 的,没仔细分析复杂度,没有调块长,甚至改题的时候也没想到这个东西,还强行上了个值域分块和bitset
二
接下来是一个真的需要值域分块和bitset的做法,复杂度是 \(O(\dfrac{n^2}{w}+n\sqrt{n})\),并且是在线做法,薄纱上面做法
首先肯定依然需要对 \(a\) 进行分块,这回我们换个方向来做,从 D 性质入手
D 性质意味着我们不再有数组 \(b\) 了,只剩下 \(a\),要求的就是询问的 \(a\) 区间与可达点的交集中最大的 \(a\) 权值
那么现在我们可以使用 bitset 存每一块中的点所对应的标号,之后从大到小遍历每一块,如果和可达点有交,证明答案一定在这一段内
暴力去做的话复杂度是 \(O(\dfrac{n^2}{w}\sqrt{n})\) 发现复杂度瓶颈在于遍历所有整块,而且一个事实是修改是 \(O(1)\) 的
那么我们发现可以维护各个块的后缀和,之后在整块上二分即可做到 \(O(\sqrt n)\) 修改 \(O(\dfrac{n}{w}\log\sqrt{n})\) 回答询问
这时候已经可以通过性质 D 了,考虑扩展
发现同时有 \(a\),\(b\) 的时候可以对 \(a\),\(b\) 同时分块,然后同时维护上面那个东西(合法的点的集合),因为是排列,所以 bitset 是可以差分的,查询和可达点的交就是 \(O(\dfrac{n^2}{w})\) 的,后面半部分在 \(b\) 上做就好了
为了通过所有数据,我们还需要去掉那个 \(\log n\)(感觉其实调一下块长是不是也没什么问题),发现在后缀和的形式中交一定是单调的
初始认为答案在第0块,手写bitset,遍历每一位,如果当前下一块的这一位的 ull 和这个和上面的合法的点有交,说明答案一定在下一块或者更后面的位置,指针加,否则的话说明bitset前面的点不会有其他贡献
这样的话查询只需要遍历整个bitset,复杂度 \(O(\dfrac{n^2}{w}+n\sqrt{n})\)
贴个代码
#include<bits/stdc++.h>
using namespace std;
using llt=long long;
using ull=unsigned long long;
const int N=100010,W=64,B=400,Len=N/W+1;
int c,T,n,m,q,a[N],ra[N],b[N],rb[N],in[N],S,L[N],R[N];bool U[N];
struct GRAPH
{
int head[N],to[N<<1],nxt[N<<1],siz;
void add(int st,int ed){to[++siz]=ed,nxt[siz]=head[st],head[st]=siz;}
void clear(){for(int i=1;i<=n;i++) head[i]=0;siz=0;}
}G;
struct BITSET
{
ull a[Len];
void reset(){memset(a,0,sizeof(a));}
void mod(int id,bool val)
{
int u=0;while(id>=W) id-=W,u++;
if(val) a[u]|=(1ull<<id);
else a[u]&=~(1ull<<id);
}
BITSET & operator |=(BITSET &rhs){for(int i=0;i<Len;i++) this->a[i]|=rhs.a[i];return *this;}
BITSET & operator &=(BITSET &rhs){for(int i=0;i<Len;i++) this->a[i]&=rhs.a[i];return *this;}
BITSET & operator ^=(BITSET &rhs){for(int i=0;i<Len;i++) this->a[i]^=rhs.a[i];return *this;}
bool get(int id){int u=0;while(id>=W) id-=W,u++;return (a[u]>>id)&1;}
ull & operator[](int id){return a[id];}
}bit[N],Ba[N/B+1],Bb[N/B+1],us;
void Pre(int now)
{
U[now]=1;bit[now].mod(now,1);
for(int i=G.head[now];i;i=G.nxt[i])
{
if(!U[G.to[i]]) Pre(G.to[i]);
bit[now]|=bit[G.to[i]];
}
}
int main()
{
#ifdef LOCAL
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
scanf("%d%d",&c,&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&q);S=0;
for(int i=1;i<=m;i++){int u,v;scanf("%d%d",&u,&v),G.add(u,v);}
for(int i=1;i<=n;i++) {if(i%B==1) R[S]=i-1,S++,L[S]=i;in[i]=S;}R[S]=n;
for(int i=1;i<=n;i++) scanf("%d",&a[i]),ra[a[i]]=i,Ba[in[a[i]]].mod(i,1);
for(int i=1;i<=n;i++) scanf("%d",&b[i]),rb[b[i]]=i,Bb[in[b[i]]].mod(i,1);
for(int i=1;i<=n;i++) if(!U[i]) Pre(i);
for(int i=S-1;i>=0;i--) Ba[i]|=Ba[i+1],Bb[i]|=Bb[i+1];
for(int i=1;i<=q;i++)
{
int op,u,v,w;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d",&u,&v);
if(a[u]>a[v]) swap(u,v);
for(int i=in[a[u]]+1;i<=in[a[v]];i++) Ba[i].mod(u,1);
for(int i=in[a[u]]+1;i<=in[a[v]];i++) Ba[i].mod(v,0);
swap(a[u],a[v]);ra[a[u]]=u;ra[a[v]]=v;
}
else if(op==2)
{
scanf("%d%d",&u,&v);
if(b[u]>b[v]) swap(u,v);
for(int i=in[b[u]]+1;i<=in[b[v]];i++) Bb[i].mod(u,1);
for(int i=in[b[u]]+1;i<=in[b[v]];i++) Bb[i].mod(v,0);
swap(b[u],b[v]);rb[b[u]]=u;rb[b[v]]=v;
}
else
{
scanf("%d%d%d",&w,&u,&v);
us.reset();
if(in[u]==in[v]){for(int i=u;i<=v;i++) us.mod(ra[i],1);}
else
{
us=Ba[in[v]];us^=Ba[in[u]+1];
for(int i=u;i<=R[in[u]];i++) us.mod(ra[i],1);
for(int i=L[in[v]];i<=v;i++) us.mod(ra[i],1);
}
us&=bit[w];int to=0;
for(int i=0;i<Len&&to<S;)
{
if((Bb[to+1][i]&us[i])!=0) to++;
else i++;
}
if(to==0) puts("0");
else
{
for(int i=R[to];i>=L[to];i--)
if(us.get(rb[i])) {printf("%d\n",i);break;}
}
}
}
G.clear();for(int i=1;i<=n;i++) U[i]=0,bit[i].reset();for(int i=1;i<=S;i++) Ba[i].reset(),Bb[i].reset();
}
return 0;
}
浙公网安备 33010602011771号