[HNOI2010]弹飞绵羊

题目链接

题解

不会lct(好想学啊T_T)

分块

记录每个点跳出当前块需要的步数和跳出块到达的点

Code

#include<bits/stdc++.h>

#define LL long long
#define RG register

using namespace std;

inline int gi() {
	RG int x = 0; RG char c = getchar(); bool f = 0;
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') c = getchar(), f = 1;
	while (c >= '0' && c <= '9') x = x*10+c-'0', c = getchar();
	return f ? -x : x;
}
int n, block;
const int N = 200010;
int l[N], r[N], K[N], st[N], pt[N], belong[N], cnt;

inline int calc(int x) {
	int tmp = 0;
	while (x) {
		tmp += st[x];
		x = pt[x];
	}
	return tmp;
}

int main() {
	n = gi(); block = sqrt(n);
	for (int i = 1; i <= n; i++) K[i] = gi();
	if (n%block) cnt = n/block+1;
	else cnt = n/block;
	for (int i = 1; i <= n; i++)
		belong[i] = (i-1)/block+1;
	for (int i = 1; i <= cnt; i++)
		l[i] = block*(i-1)+1, r[i] = block*i;
	r[cnt] = n;
	for (int i = n; i > 0; i--)
		if (belong[i] == belong[i+K[i]]) st[i] = st[i+K[i]]+1, pt[i] = pt[i+K[i]];
		else st[i] = 1, pt[i] = K[i]+i;
	int m = gi();
	while (m--) {
		int type = gi(), x = gi()+1;
		if (type == 1) printf("%d\n", calc(x));
		else {
			int y = gi(); K[x] = y;
			for (int i = x; i >= l[belong[x]]; i--)
				if (belong[i] == belong[i+K[i]]) st[i] = st[i+K[i]]+1, pt[i] = pt[i+K[i]];
				else st[i] = 1, pt[i] = K[i]+i;
		}
	}
	return 0;
}

posted @ 2018-12-18 09:37  zzy2005  阅读(95)  评论(0编辑  收藏  举报