• Bounce 弹飞绵羊 --- 分块/LCT/动态树


    https://www.lydsy.com/JudgeOnline/problem.php?id=2002

    分块(

    LCT()

    动态树()

    一、分块:

    分块重要的是确定我们建立的数组要完成什么使命,这题是问从某点弹出序列需要几次,并要提供修改操作。既然分了块,那我们就要把操作缩小到块的范围,需要的是弹出整个序列的次数,我们就缩小到跳出这个块的次数;而最后query时就像并查集一样(?)一块一块地去找它的祖宗,所以再给它提供一个数组存这个点的落地位置。

    tips:1)存次数和落地位置用结构体好像比两个独立的数组要快一些,但我不会分析o( ̄┰ ̄*)ゞ

              2)要用scanf,不然tle到崩溃

     1 #include<bits/stdc++.h>
     2 #define mem(a) memset(a,0,sizeof(a))
     3 #define ll long long
     4 #define inf 0x3f3f3f3f
     5 const int N=2e5+5;
     6 const int M=1e3+10;
     7 const ll lim=1e14+5;
     8 using namespace std;
     9 int mod=1e9+7;
    10 int a[N],sum[N];
    11 int blo,l[N],r[N];
    12 int n,belong[N],k,num;
    13 struct node{
    14    int cnt,tag;
    15 }lazy[N];
    16 void build()
    17 {
    18     blo=sqrt(n);
    19     num=n%blo>0?n/blo+1:n/blo;
    20     for(int i=1;i<=num;i++)
    21     {
    22         l[i]=(i-1)*blo+1;
    23         r[i]=i*blo;
    24     }
    25     r[num]=n;
    26     for(int i=1;i<=n;i++)
    27         belong[i]=(i-1)/blo+1;
    28     for(int i=n;i>0;i--)
    29     {
    30        if(a[i]+i>n)
    31         lazy[i].cnt=1;
    32        else if(belong[i]==belong[a[i]+i])
    33        {
    34            lazy[i].cnt=lazy[a[i]+i].cnt+1;
    35            lazy[i].tag=lazy[a[i]+i].tag;
    36            //因为i下一个会跳到a[i]+1位置,所以跳出块外的地方与后者一样
    37        }
    38        else
    39        {
    40            lazy[i].cnt=1;
    41            lazy[i].tag=i+a[i];
    42        }
    43     }
    44 }
    45 void add(int x,int c)
    46 {
    47    a[x]=c;
    48    for(int i=x;i>=l[belong[x]];i--)
    49     if(belong[i]==belong[i+a[i]])
    50       lazy[i].cnt=lazy[a[i]+i].cnt+1,lazy[i].tag=lazy[i+a[i]].tag;
    51     else
    52       lazy[i].cnt=1,lazy[i].tag=i+a[i];
    53 }
    54 int query(int x)
    55 {
    56     int ans=0;
    57     while(1)
    58     {
    59         ans+=lazy[x].cnt;
    60         if(!lazy[x].tag) break;
    61         x=lazy[x].tag;
    62     }
    63     return ans;
    64 }
    65 int main(){
    66     int m;
    67     scanf("%d",&n);
    68     for(int i=1;i<=n;i++)
    69         scanf("%d",&a[i]);
    70     scanf("%d",&m);
    71     build();
    72     int i,j,k;
    73     while(m--)
    74     {
    75         scanf("%d%d",&i,&j);
    76         ++j;
    77         if(i==1)
    78             printf("%d
    ",query(j));
    79         if(i==2)
    80         {
    81            scanf("%d",&k);
    82             add(j,k);
    83         }
    84     }
    85     return 0;
    86 }
    View Code
  • 相关阅读:
    .net 命名规范
    解决Swagger刷新后不能保持登录问题
    修改表结构后视图错位问题
    创建.net api文档
    编写.net core tools教程
    VuePress 侧边栏几种配置
    VS 好用快捷键
    Jenkins 修改端口
    获取当前被调用的方法
    遇到异常 add-migration Build failed 解决办法
  • 原文地址:https://www.cnblogs.com/XXrll/p/11132417.html
Copyright © 2020-2023  润新知