Catalog
题解 P3203 【[HNOI2010]弹飞绵羊】

查看原题请戳这里
我们先来看一下这道题如果先转化成森林再处理的话,一共有如下几个操作:

  • 删除一条边
  • 加入一条边
  • 查询两点间路径权值和

这不是一道LCT的题吗……
然而LCT代码复杂度太高了,这里我们来讲一下如何用分块来解决这道题。
首先,我们将这$n$个装置分成$\sqrt n$块,每块有$\sqrt n$个元素。然后,我们记录下每个元素跳出ta所在块所需要的步数以及ta会跳到哪里。然后,对于每次修改,我们就用$O(n)$的复杂度去修改一个块中所有元素的值;对于每次查询,我们就一个块一个块条。
时间复杂度:$O(\sqrt n)$
code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define ll long long
#define INF 0x7fffffff
#define re register
#define qwq printf("qwq\n");

using namespace std;

int read()
{
register int x = 0,f = 1;register char ch;
ch = getchar();
while(ch > '9' || ch < '0'){if(ch == '-') f = -f;ch = getchar();}
while(ch <= '9' && ch >= '0'){x = x * 10 + ch - 48;ch = getchar();}
return x * f;
}

int n,m,x,y,z,a[200005],l[100005],r[100005],len,num,to[200005],cnt[200005],blog[200005];

void clannad(int k)
{
for(int i = r[k]; i >= l[k]; i--)
{
blog[i] = k;
if(i + a[i] > r[k]) to[i] = i + a[i],cnt[i] = 1;
else to[i] = to[i + a[i]],cnt[i] = cnt[i + a[i]] + 1;
}
}

void change(int k)
{
int u = blog[k];
for(int i = k; i >= l[u]; i--)
{
if(i + a[i] > r[u]) to[i] = i + a[i],cnt[i] = 1;
else to[i] = to[i + a[i]],cnt[i] = cnt[i + a[i]] + 1;
}
}

int query(int k,int sum)
{
if(k > n) return sum;
return query(to[k],sum + cnt[k]);
}

int main()
{
n = read();
for(int i = 1; i <= n; i++) a[i] = read();
len = sqrt(n);
num = n / len;
if(n % len) num++;
for(int i = 1; i <= num; i++) l[i] = (i - 1) * len + 1,r[i] = i * len;
r[num] = n;
for(int i = 1; i <= num; i++) clannad(i);
m = read();
for(int i = 1; i <= m; i++)
{
x = read(); y = read() + 1;
if(x == 1) printf("%d\n",query(y,0));
if(x == 2)
{
z = read();
a[y] = z;
change(y);
}
}
return 0;
}
Author: wflight
Link: http://yoursite.com/2019/08/14/题解-P3203-【-HNOI2010-弹飞绵羊】/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.
Donate
  • 微信
  • 支付寶

Comment