zoukankan      html  css  js  c++  java
  • BZOJ 2002 [Hnoi2010]Bounce 弹飞绵羊(分块)

    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=2002

    【题目大意】

      给出一片森林,操作允许更改一个节点的父亲,查询一个节点的深度。
      父亲节点的编号一定大于子节点

    【题解】

      我们将所有的节点按照序号分块,记录其到下一个分块的深度,
      以及其可以跳到下一个分块的位置,
      那么修改节点的父亲对于所存储的数据的影响就被缩小到一个块内,单次修改sqrt(n)。

      动态树做法:链接

    【代码】

    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N=200010;
    int n,m,op,pos[N],block,l[N],r[N],K[N],d[N],nxt[N];
    int cal(int x){for(int res=0;;x=nxt[x]){res+=d[x];if(!nxt[x])return res;}}
    int main(){
        scanf("%d",&n);
        block=sqrt(n+0.5);
        for(int i=1;i<=n;i++)scanf("%d",&K[i]);
        if(n%block)m=n/block+1; 
        else m=n/block;
        for(int i=1;i<=m;i++)l[i]=(i-1)*block+1,r[i]=i*block; r[m]=n;
        for(int i=1;i<=n;i++)pos[i]=(i-1)/block+1;
        for(int i=n;i;i--){
            if(i+K[i]>n)d[i]=1;
            else if(pos[i]==pos[i+K[i]])d[i]=d[i+K[i]]+1,nxt[i]=nxt[i+K[i]];
            else d[i]=1,nxt[i]=i+K[i];
        }scanf("%d",&op);
        while(op--){
            int u,x,y;
            scanf("%d%d",&u,&x);x++;
            if(u==1)printf("%d
    ",cal(x));
            else{
                scanf("%d",&y); K[x]=y;
                for(int i=x;i>=l[pos[x]];i--)if(pos[i]==pos[i+K[i]]){
                    d[i]=d[i+K[i]]+1; nxt[i]=nxt[i+K[i]];
                }else d[i]=1,nxt[i]=i+K[i];
            }
        }return 0;
    }
  • 相关阅读:
    linux 免密登录
    mysql 重置从库
    elasticsearch原理及简介
    多线程编程--心得
    为什么我们做分布式使用Redis?
    JAVA-JVM调优
    JAVA-JVM调优标志
    Spirng-Mvc之Servlet篇
    Agent Job代理 执行SSIS Package
    Python之爬虫的理解
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj2002plus.html
Copyright © 2011-2022 走看看