专栏文章
[省选联考 2025] 追忆 题解
P11831题解参与者 3已保存评论 3
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 3 条
- 当前快照
- 1 份
- 快照标识符
- @miq3jqi8
- 此快照首次捕获于
- 2025/12/03 22:22 3 个月前
- 此快照最后确认于
- 2025/12/03 22:22 3 个月前
思路可以见游记。
这是一个很暴力的考场做法,似乎没看见跟我一样的。
首先有向图可达性算是比较典的 ,正好题目也提示了我们空间和时间都很大,所以这个肯定对完了。具体地,预处理 个 bitset 表示 是否可达 。查询的时候相当于查询 中所有 在值域中的 的最大值。
然后这两个带修看上去都非常不容易,好像只会 ABC 性质但是又没有。考察思考的方向,注意到如果 可达集合是 所有点的话不弱于动态二维数点,而这个题已经有一个平方级别的暴力部分了所以不妨完全放弃 polylog 开始想分块之类的暴力结构。
尝试解决 上的值域限制。一个基于 静态的想法是,处理 的每个值域前缀对应的下标和。即 表示所有 的 的集合组成的 bitset。这样至少可以在每次询问中 地去除 的限制,似乎是不错的。再仔细一想,这个空间似乎已经是两倍的 ,一定会很卡,所以考虑放弃。
这种前缀和相关的题需要注意到,如果查询的复杂度和预处理的复杂度很不平衡,可以套用一些看上去几乎无意义的分块来压缩空间(有一个较深的印象是我和 irris 的这个题的这篇题解)。注意到我们分块之后,查询的时候的单点修改的复杂度是非常小的,是小常数 ,然而查询整块非常耗费时间。而我们非常经得起大量的散块查询,在 的时候把块长开到 都可以接受。于是可以细想分块了!
不妨按 分块。说人话就是只维护所有 的 的 。这样还有一个好处是,对 的单点修改只会改到 个 ,所以 也可以接受了。查询的时候相当于需要支持查询单点 ,可以先调用 ,再把缺的单点部分暴力补上。这整个部分时间复杂度是 。
实际上这个时候写一个取出所有符合要求的点求 可以在最后一个大样例跑 7s,几乎可以通过了。
然后考虑如何优化 的部分。可以发现即使是静态问题都没有什么优秀的做法。直接枚举或者直接分块显然没有什么理论低于 的做法。
考虑为什么要我们求 呢?有一个直接的想法是二分答案,变成判定给定 bitset 和 的值域区间是否有交。不妨把 的值域取反变成前缀(方便我自己理解),类似上面地设计 表示所有 的 组成的 bitset(这里似乎和块长的字母重复了,那就随便新取一个)。在不带修的时候可以做到 。感觉很蠢,还不能带修。但是 的修改是否可以参考 的修改呢?
这就不得不提到 WC 文艺汇演的相声(这句话也给了我相当的启发):
找一个数在有序序列中的出现位置的时候,先分块!二分它在哪个块里,然后在块里二分!就做到了 !
可以想到仍然对 分块,维护方法同 。查询的时候直接二分它在哪个块里(因为只维护了整块信息,查询还方便),然后暴力查询块内,这样完美平衡了一下单点查询的 和整块前缀查询的 !
具体地,维护所有整块代表的 bitset 的前缀和。查询的时候在大块上查询,可以极大的削掉 的部分。check 的时候只需要拿 和当前询问的 bitset 判断交是否非空即可。对于散块,暴力查询的 还是很可观的!同时分块仍然可以支持带修!这部分时间复杂度 。具体 取啥的时候最优懒得算了,反正我直接取 在大样例跑了 2.3s。此时 只有 ,至少少了三倍常数。上下取同一个 ,总时间复杂度就是 。
建议手写 bitset,理由不知道。
考场代码:
CPP#include<bits/stdc++.h>
#define MOD 998244353
#define int long long
#define REP(i,a,n) for(int i=(a);i<(int)(n);++i)
#define pii pair<int,int>
#define pb push_back
#define all(v) v.begin(),v.end()
#define over {cout<<x<<"\n";return;}
using namespace std;
int read(){
int res=0;char c=getchar();
while(c<48||c>57)c=getchar();
do res=(res<<1)+(res<<3)+(c^48),c=getchar();while(c>=48&&c<=57);
return res;
}
int qpow(int a,int b,int m=MOD){
int res=1;
while(b)res=b&1? res*a%m:res,a=a*a%m,b>>=1;
return res;
}
#define ui unsigned int
int ID;
vector<int>v[100005];
int n,m,q,BL,CL;
ui C[100000][1563];
ui A[400][1563];
ui B[400][1563];
int a[100000],b[100000],ia[100000],ib[100000];
ui qr[1563];
void updA(int x,int y){
REP(i,x/BL,CL)A[i][y>>6]^=1ull<<(y&63);
}
void updB(int x,int y){
REP(i,x/BL,CL)B[i][y>>6]^=1ull<<(y&63);
}
void opA(int x){
int d=x/BL-1;
if(x>=BL){
REP(j,0,m)qr[j]^=A[d][j];
}
REP(i,x/BL*BL,x+1)qr[ia[i]>>6]^=1ull<<(ia[i]&63);
}
void Main(){
n=read();m=read();q=read();
REP(i,0,n)v[i].clear();
REP(i,0,m){
int x,y;
x=read()-1;y=read()-1;
v[x].pb(y);
}
m=(n-1)>>6;++m;
for(int i=n-1;i>=0;--i){
REP(j,i>>6,m)C[i][j]=0;
C[i][(i>>6)]=1ull<<(i&63);
for(auto j:v[i]){
REP(l,j>>6,m)C[i][l]|=C[j][l];
}
}
BL=sqrt(n*7);BL=min(BL,n);
BL=min(2000ll,n);
CL=(n-1)/BL+1;
REP(i,0,n){
a[i]=read()-1;
ia[a[i]]=i;
}
REP(i,0,n){
int d=i/BL;
if(i%BL==0){
if(i){
REP(j,0,m)A[d][j]=A[d-1][j];
}else{
REP(j,0,m)A[d][j]=0;
}
}
A[d][ia[i]>>6]|=1ull<<(ia[i]&63);
}
REP(i,0,n)b[i]=n-read(),ib[b[i]]=i;
REP(i,0,n){
int d=i/BL;
if(i%BL==0){
if(i){
REP(j,0,m)B[d][j]=B[d-1][j];
}else{
REP(j,0,m)B[d][j]=0;
}
}
B[d][ib[i]>>6]|=1ull<<(ib[i]&63);
}
REP(i,0,q){
int op,x,y,l,r;
op=read();
if(op==1){
x=read()-1;y=read()-1;
swap(a[x],a[y]);
x=a[x];y=a[y];
updA(x,ia[x]);updA(x,ia[y]);
updA(y,ia[y]);updA(y,ia[x]);
swap(ia[x],ia[y]);
}else if(op==3){
x=read()-1;l=read()-1;r=read()-1;
REP(j,0,m)qr[j]=0;
if(l)opA(l-1);
opA(r);
REP(j,0,m)qr[j]&=C[x][j];
int ans=0,fl=0;
REP(j,0,m){
if(qr[j])fl=1;
}
if(!fl){
cout<<0<<'\n';
continue;
}
int l=0,r=CL-1,res=r;
while(l<=r){
int mid=(l+r)>>1,f=0;
REP(j,0,m)if(B[mid][j]&qr[j]){f=1;break;}
if(f)res=mid,r=mid-1;
else l=mid+1;
}
for(int i=res*BL;i<n;++i){
int x=ib[i];
if(qr[x>>6]&(1ull<<(x&63))){
ans=i;
break;
}
}
cout<<n-ans<<'\n';
}else{
x=read()-1;y=read()-1;
swap(b[x],b[y]);
x=b[x];y=b[y];
updB(x,ib[x]);updB(x,ib[y]);
updB(y,ib[y]);updB(y,ib[x]);
swap(ib[x],ib[y]);
}
}
}
signed main(){
freopen("recall.in","r",stdin);
freopen("recall.out","w",stdout);
int tc=1;
ID=read();tc=read();
while(tc--)Main();
return 0;
}
相关推荐
评论
共 3 条评论,欢迎与作者交流。
正在加载评论...