题意:现在有一排洞,每个洞有一个弹力,能弹到ai之后的洞,球会弹到这个排的外面,现在有2个操作,0 a b 将第a个洞的弹力设为b, 1 a 将球放入第a个洞,求输出进洞的次数 和 弹出这排洞进入的最后一个洞。
题解:分块暴力,对于每一个块,记录下这每一个点到下一个块的入口位置,和在这个块的最后到的点,还有就是进洞次数。然后每次修改的时候,暴力更新这个块的前半部分就好了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout); 4 #define LL long long 5 #define ULL unsigned LL 6 #define fi first 7 #define se second 8 #define pb push_back 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define max3(a,b,c) max(a,max(b,c)) 12 #define min3(a,b,c) min(a,min(b,c)) 13 #define _S(X) cout << x << ' '; 14 #define __S(x) cout << x << endl; 15 typedef pair<int,int> pll; 16 const int INF = 0x3f3f3f3f; 17 const LL mod = (int)1e9+7; 18 const int N = 1e5 + 100; 19 int belong[N], l[N], r[N]; 20 int to[N], tto[N], cnt[N], fin[N]; 21 int n, m, tot, q, op, k, v; 22 void PushDown(int x){ 23 int idx = belong[x]; 24 for(int i = x; i >= l[idx]; i--){ 25 if(to[i] > r[idx]) tto[i] = to[i], cnt[i] = 1, fin[i] = i; 26 else { 27 tto[i] = tto[to[i]]; 28 cnt[i] = cnt[to[i]] + 1; 29 fin[i] = fin[to[i]]; 30 } 31 } 32 } 33 void Build(){ 34 m = sqrt(n); 35 tot = n/m; 36 if(n%m) tot++; 37 for(int i = 1; i <= n; i++){ 38 cnt[i] = 0; 39 belong[i] = (i-1) / m + 1; 40 } 41 for(int i = 1; i <= tot; i++){ 42 l[i] = (i-1)*m + 1; 43 r[i] = i*m; 44 } 45 r[tot] = n; 46 for(int i = 1; i <= tot; i++) 47 PushDown(r[i]); 48 } 49 void Query(int x){ 50 int ret = 0, y = x, t; 51 while(x != n+1){ 52 ret += cnt[x]; 53 y = fin[x]; 54 x = tto[x]; 55 } 56 printf("%d %d ", y, ret); 57 } 58 int main(){ 59 scanf("%d%d", &n, &q); 60 for(int i = 1; i <= n; i++){ 61 scanf("%d", &to[i]); 62 to[i] += i; 63 if(to[i] > n) to[i] = n+1; 64 } 65 Build(); 66 while(q--){ 67 scanf("%d", &op); 68 if(op == 0){ 69 scanf("%d", &k); 70 scanf("%d", &to[k]); 71 to[k] += k; 72 if(to[k] > n) to[k] = n+1; 73 PushDown(k); 74 } 75 else { 76 scanf("%d", &k); 77 Query(k); 78 } 79 } 80 return 0; 81 }