正解是动态树,太难了,仅仅好分块处理水之。看了看status大概慢了一倍之多。。
分块算法大体就是在找一个折衷点,使得查询和改动的时间复杂度都不算太高,均为o(sqrt(n)),所以总的时间复杂度为o(m*sqrt(n))。
分块的大体思想就是将整段区间分成sqrt(n),每次改动影响所在段内的sqrt(n)个点。每次查询遍历sqrt(n)段,然后搞出一些事情。
对于此题,首先说明几个数组的含义:
cnt[i]的意义为从i点開始跳出其所在段所须要的步数。
goal[i]的意义为从i点開始所经历的最后一个点。
jmp[i]的意义为从i点開始跳出所在段之后第一个到达点。
明确了这几个意义之后看代码就好了,文字太无力。
分块算法大体就是在找一个折衷点,使得查询和改动的时间复杂度都不算太高,均为o(sqrt(n)),所以总的时间复杂度为o(m*sqrt(n))。
分块的大体思想就是将整段区间分成sqrt(n),每次改动影响所在段内的sqrt(n)个点。每次查询遍历sqrt(n)段,然后搞出一些事情。
对于此题,首先说明几个数组的含义:
cnt[i]的意义为从i点開始跳出其所在段所须要的步数。
goal[i]的意义为从i点開始所经历的最后一个点。
jmp[i]的意义为从i点開始跳出所在段之后第一个到达点。
明确了这几个意义之后看代码就好了,文字太无力。
#include <algorithm> #include <iostream> #include <cstring> #include <cstdlib> #include <cstdio> #include <queue> #include <cmath> #include <stack> #include <map> #include <ctime> #include <iomanip> #pragma comment(linker, "/STACK:1024000000"); #define EPS (1e-6) #define LL long long #define ULL unsigned long long #define _LL __int64 #define INF 0x3f3f3f3f #define Mod 1000000007 using namespace std; const int MAXN = 100010,BLOCK = sqrt(100010); int jmp[MAXN],cnt[MAXN],goal[MAXN],val[MAXN]; void Updata(int x,int y,int n) { if(y > n) { jmp[x] = MAXN; cnt[x] = 1; goal[x] = x; } else if(x/BLOCK*BLOCK == y/BLOCK*BLOCK) { jmp[x] = jmp[y]; cnt[x] = cnt[y]+1; goal[x] = goal[y]; } else { jmp[x] = y; cnt[x] = 1; goal[x] = y; } } void Cal(int x) { int ans = 0,f; while(x != MAXN) { f = goal[x]; ans += cnt[x]; x = jmp[x]; } printf("%d %d ",f,ans); } int main() { int i,j,u,v,n,m,ord,L; scanf("%d %d",&n,&m); for(i = 1;i <= n; ++i) scanf("%d",&val[i]); for(i = n;i >= 1; --i) Updata(i,i+val[i],n); while(m--) { scanf("%d",&ord); if(ord) { scanf("%d",&u); Cal(u); } else { scanf("%d %d",&u,&v); val[u] = v; L = u/BLOCK*BLOCK; for(i = u;i >= L; --i) Updata(i,i+val[i],n); } } return 0; }