【AGC012E】 Camel and Oases ST表+状压dp
题目大意:一排点,两点间有距离。 初始你有一个行走值v,如果相邻两点距离不超过v你可以自由在这两点行走。
当v大于0时,你可以选择某一时刻突然飞到任意点,这样做后v会减半(下取整)。 问从每个位置初始出发能否到达所有位置。
点的数量≤2∗105,v≤2∗105,|两点距离|≤109。
我们令l[i][j]表示从i出发,一路往左走,经过所有长度不超过v>>j(此处的>>表示右移,以下都是)的边,能走到最左的点的编号。
令r[i][j]表示从i出发,一路往右走,经过所有长度不超过v>>j的边,能走到最右的点的编号。
令n表示点的数量,m=⌈log2v⌉。
我们不难得出:从u号点出发,是否可以遍历完所有点的判断条件,可以转化为:
是否可以将点集分成m+1个块,且第i(从0到m)个块内边的长度均不超过v>>i,且第u号点需要在第0个块内。
那么,对于[1,2m)中的每一个i(i是一个二进制状态,i的第j(j从1到m)位为1表示选择了图中第j个块)
求一个最大的f[i],满足区间[1,f[i]]中的点能分成由状态i表示的若干个块。
同理,求一个最小的g[i],满足区间[g[i],n]中的点能分成由状态i表示的若干个块。
求这个可以通过l和r的值+状压dp实现,时间复杂度是O(v log v)。
我们令o=2m−2。
我们发现,若存在i,使得r[f[i]][0]>=l[g[o^i]][0],那么从区间[ l[g[o^i]][0] , r[f[i]][0] ]中出发的点,显然可以遍历玩所有点。
我们可以O(1)打上一个标记,求答案的时候O(n)扫一遍,判断某个点是否被打了标记即可。
总时间复杂度:O(n log v+v log v)。
1 #include<bits/stdc++.h> 2 #define M 400005 3 #define YXQAK printf("Possible\n") 4 #define XFZBL printf("Impossible\n"); 5 using namespace std; 6 7 int a[M]={0},n,m,v,l[20][M]={0},r[20][M]={0}; 8 int f[M]={0},g[M]={0},p[M]={0}; 9 10 int main(){ 11 scanf("%d%d",&n,&v); 12 for(int i=1;i<=n;i++) scanf("%d",a+i); 13 sort(a+1,a+n+1); 14 for(int j=0,V=v;V;j++,V>>=1){ 15 m=max(m,j); 16 for(int i=1;i<=n;i++){ 17 int I=i+1; 18 while(I<=n&&a[I]-a[I-1]<=V) I++; 19 I--; 20 for(int ii=i;ii<=I;ii++) 21 l[j][ii]=i,r[j][ii]=I; 22 i=I; 23 } 24 } 25 m++; 26 for(int i=1;i<=n;i++) l[m][i]=r[m][i]=i; 27 for(int i=0;i<(1<<m);i++) g[i]=n; f[0]=1; 28 for(int i=1;i<(1<<m);i++){ 29 int now=1; 30 for(int j=m-1;~j;j--) 31 if((1<<j)&i) 32 f[i]=max(f[i],r[j+1][f[i^(1<<j)]]+1); 33 34 now=n; 35 for(int j=m-1;~j;j--) 36 if((1<<j)&i) 37 g[i]=min(g[i],l[j+1][g[i^(1<<j)]]-1); 38 } 39 40 for(int i=0;i<(1<<m);i++){ 41 if(r[0][f[i]]+1>=l[0][g[(1<<m)-i-1]]) 42 p[l[0][g[(1<<m)-i-1]]]++,p[r[0][f[i]]+1]--; 43 } 44 for(int i=1;i<=n;i++){ 45 p[i]+=p[i-1]; 46 if(p[i]) YXQAK; 47 else XFZBL; 48 } 49 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!