zoukankan      html  css  js  c++  java
  • [HNOI2010] 弹飞绵羊 bounce

    标签:分块。
    题解:

      200000,而且标号从0开始,很符合分块的条件啊。看看怎么实现。
      首先分成√n个区间,然后如果我们对于每一个位置i,求出一个Next[i]和step[i],分别表示跳到的后一个位置与步数,因为是分块所以就是跳到下一个区间的步数与位置了。处理这两个数组要从前到后,只需要O(n)。
      然后查询:自然是使用这两个数组,跳出去就return,复杂度O(√n)。
      修改:修改一个点自然是O(1),但是前面的会跳到这个地方,那不是前面的都要改?非也,因为Next[]仅仅跨越了一个区间,所有最多有这个区间的起始位置到i个是需要更改的,也就是最大√n个,我们从i到起始位置烦着枚举,复杂度O(√n)。
      所以总的复杂度为O(m√n)。

     1 #include<cmath>
     2 #include<cstdio>
     3 #include<iostream>
     4 #include<algorithm>
     5 using namespace std;
     6 const int MAXN=210000;
     7 int n,m,cnt;
     8 int W[MAXN],Next[MAXN],step[MAXN],team[MAXN];
     9 inline int gi(){int res; scanf("%d",&res); return res;}
    10 void update(int p)
    11 {
    12   if(p+W[p]>=n)
    13     {
    14       step[p]=1;
    15       Next[p]=n;
    16       return ;
    17     }
    18   int net=p+W[p];
    19   if(team[p]==team[net])
    20     {
    21       step[p]=step[net]+1;
    22       Next[p]=Next[net];
    23     }
    24   else
    25     {
    26       step[p]=1;
    27       Next[p]=net;
    28     }
    29 }
    30 int query(int p)
    31 {
    32   int res=0;
    33   while(p!=n)
    34     {
    35       res+=step[p];
    36       p=Next[p];
    37     }  
    38   return res;
    39 }
    40 int main()
    41 {
    42   n=gi(); cnt=sqrt(n);
    43   for(int i=0;i<n;i++) W[i]=gi();
    44   for(int i=0;i<n;i++) team[i]=i/cnt;
    45   for(int i=n-1;i>=0;i--) update(i);
    46   m=gi();
    47   while(m--)
    48     {
    49       int op=gi(),p=gi();
    50       if(op==2)
    51         {
    52           int w=gi();
    53           W[p]=w;
    54           for(int i=p;i>=0;i--)
    55             if(team[p]==team[i])
    56               update(i);
    57             else
    58               break;
    59         }
    60       else
    61         printf("%d
    ",query(p));
    62     }
    63   return 0;
    64 }

    标签:LCT
    题解:

      此题当然不缺乏LCT做法,对于LCT来说,这道题就是一道模板题,每次修改cut再link,维护sz代表子树的大小。使用一个根节点:n+1,也就是跳出去。M+A+S,查询x的左子树大小即可,也就是比他深度小的点的个数,不就是多少步跳出去吗?

     1 #include<cstdio>
     2 #include<iostream>
     3 #include<algorithm>
     4 using namespace std;
     5 const int MAXN=300099;
     6 int n,m;
     7 int fa[MAXN],rev[MAXN],val[MAXN],Q[MAXN],ch[MAXN][2],sz[MAXN];
     8 bool isroot(int x){ return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; }
     9 void Update(int x){ sz[x]=sz[ch[x][0]]+sz[ch[x][1]]+1; }
    10 bool get(int x){ return ch[fa[x]][1]==x ;}
    11 void Down(int x){ if(rev[x]){ rev[ch[x][0]]^=1; rev[ch[x][1]]^=1; rev[x]^=1; swap(ch[x][0],ch[x][1]); } }
    12 void Rotate(int x)
    13 {
    14   int old=fa[x],oldf=fa[old],op=get(x);
    15   if(!isroot(old)) ch[oldf][ch[oldf][1]==old]=x;
    16   ch[old][op]=ch[x][op^1]; fa[ch[x][op^1]]=old;
    17   ch[x][op^1]=old; fa[old]=x; fa[x]=oldf;
    18   Update(old); Update(x);
    19 }
    20 void Splay(int x)
    21 {
    22   int tp=1; Q[1]=x;
    23   for(int i=x;!isroot(i);i=fa[i]) Q[++tp]=fa[i];
    24   for(int i=tp;i;i--) Down(Q[i]);
    25   for(int FA; !isroot(x) ; Rotate(x))
    26     {
    27       FA=fa[x];
    28       if(!isroot(FA)) Rotate(get(x)==get(FA)?FA:x);
    29     }
    30 }
    31 void Access(int x){ int t=0; while(x){ Splay(x); ch[x][1]=t; Update(x); t=x; x=fa[x]; } }
    32 void Makeroot(int x){ Access(x); Splay(x); rev[x]^=1;}
    33 void Link(int x,int y){ Makeroot(x); fa[x]=y;}
    34 void Cut(int x,int y){ Makeroot(x); Access(y); Splay(y); if(ch[y][0]==x) fa[x]=ch[y][0]=0;}
    35 int main( )
    36 {
    37   scanf("%d",&n); sz[n+1]=1;
    38   for(int i=1;i<=n;i++) scanf("%d",&val[i]) , sz[i]=1;
    39   for(int i=n;i>=1;i--) Link(i,min(i+val[i],n+1));
    40   scanf("%d",&m);
    41   while(m--)
    42     { 
    43       int x,op,y,ans=0;
    44       scanf("%d%d",&op,&x); x++;
    45       if(op==1)
    46         {
    47           Makeroot(n+1); Access(x); Splay(x);
    48           printf("%d
    ",sz[ch[x][0]]);
    49         }
    50       else
    51         {
    52           scanf("%d",&y);
    53           Makeroot(n+1); Access(x);
    54           Cut(x,min(x+val[x],n+1));
    55           val[x]=y;
    56           Link(x,min(x+val[x],n+1));
    57         }
    58     }
    59   return 0;
    60 }
  • 相关阅读:
    批量清理java源码的target目录
    前端移动node_modules到其他位置
    oracle物化视图和视图的数据不一致
    百词斩英语单词素材提取、听力练习
    2048自动游戏AI, 最高可以玩出一二十个2048
    switcheroo: Alt+Tab的替代工具、窗口搜索
    为知笔记wiz.editor.md增强
    腾讯北极星 Polaris 试用
    [分布式] 分布式事务、seata
    Mysql查询所有的表名和查询表中所有的字段名
  • 原文地址:https://www.cnblogs.com/D-O-Time/p/7986396.html
Copyright © 2011-2022 走看看