CF1168C And Reachability(DP)

末蓝、 2021-11-22 15:08 353阅读 0赞

其实也不难。(自己没想到自己打自己脸)

首先定义 $g[i][j]$ 表示 $i$ 前面(不包括 $i$)第一个第 $j$ 位是 $1$ 的数的位置。可以随便转移。

再定义 $f[i][j]$ 表示 $i$ 前面(包括 $i$)第一个第 $j$ 位是 $1$ 的数,且能通过题面的操作跳到 $i$ 的位置。

也能随便转移。先判断 $i$ 自己可不可以,可以就直接搞,不可以就找一个中介位 $k$($a_i$ 的第 $k$ 位必须是 $1$),$f[g[i][k]][j]$ 一定是可以跳到的。因为 $i$ 肯定能从 $g[i][k]$ 跳到(都有第 $k$ 位),$g[i][k]$ 肯定能从 $f[g[i][k]][j]$ 跳到(定义)。

对于询问,找一个中介位 $k$($a_l$ 的第 $k$ 位必须是 $1$),那么 $r$ 可以从 $f[r][k]$ 跳到。当且仅当 $f[r][k]\ge l$ 时,$f[r][k]$ 可以从 $l$ 跳到。 所以判一下所有的 $k$ 即可。

时间复杂度 $O(n\log^2 v+q\log v)$。(代码实现优秀一点似乎可以一个 $\log$?)

ContractedBlock.gif ExpandedBlockStart.gif

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. const int maxn=300030;
  4. #define FOR(i,a,b) for(int i=(a);i<=(b);i++)
  5. #define ROF(i,a,b) for(int i=(a);i>=(b);i--)
  6. #define MEM(x,v) memset(x,v,sizeof(x))
  7. inline int read(){
  8. int x=0,f=0;char ch=getchar();
  9. while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
  10. while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
  11. return f?-x:x;
  12. }
  13. int n,q,a[maxn],f[maxn][19],g[maxn][19],hhh[19];
  14. int main(){
  15. n=read();q=read();
  16. FOR(i,1,n) a[i]=read();
  17. FOR(i,1,n){
  18. FOR(j,0,18) g[i][j]=hhh[j];
  19. FOR(j,0,18) if((a[i]>>j)&1) hhh[j]=i;
  20. }
  21. FOR(i,1,n){
  22. FOR(j,0,18) if((a[i]>>j)&1) f[i][j]=i;
  23. else FOR(k,0,18) if((a[i]>>k)&1) f[i][j]=max(f[i][j],f[g[i][k]][j]);
  24. }
  25. while(q--){
  26. int l=read(),r=read();
  27. bool flag=false;
  28. FOR(i,0,18) if((a[l]>>i)&1) flag|=f[r][i]>=l;
  29. puts(flag?"Shi":"Fou");
  30. }
  31. }

转载于:https://www.cnblogs.com/1000Suns/p/11116736.html

发表评论

表情:
评论列表 (有 0 条评论,353人围观)

还没有评论,来说两句吧...

相关阅读

    相关 [CF559 C]Gerald and Giant Chess

    题面描述 给定一个\\(H\W\\)的棋盘,棋盘上只有\\(N\\)个格子是黑色的,其他格子都是白色的。在棋盘左上角有一个卒,每一步可以向右或者向下移动一格,并且不能移动