您的位置:首页 > 其它

【bzoj2022】弹飞绵羊

2016-03-31 22:00 302 查看
我不会LCT

QAQQQQQQQ

DQS:“LCT一个log跑的比两个log还慢”

xczhw:“我告诉你他跑的比sqrt还慢……”



这题细节挺多的……

不过中心思想就是一句话:“记录一个点跳到块外的步数以及落脚点”

恩恩就是这样

查找就很好查找了……

修改的时候只修改同一个块内的就好

void change(int x,int v)
{
num[x] = v;//ki
step[x] = 1;//跳到块外用的步数
int mx = x / M,nxt = min(n,x + v);//下一个
next[x] = nxt;//cnbb就这里让我wa了半天
if((nxt) / M == mx)
{
step[x] += step[nxt];
next[x] = next[nxt];
}
int r = x - 1;
while((r + 1) % M)
{
nxt = min(n,r + num[r]);
if(nxt / M == mx)
{
step[r] = step[nxt] + 1;
next[r] = next[nxt];
}
r--;
}
return;
}


#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
using namespace std;
const int MAXN = 200000 + 5;
int n,m,M;
int num[MAXN],next[MAXN],step[MAXN];
void init()
{
M = sqrt(n) + 1;
for(int i = n - 1;i >= 0;i --)
{
int nxt = min(n,i + num[i]);
if(nxt / M == i / M)
{
step[i] = step[nxt] + 1;
next[i] = next[nxt];
}
}
return;
}
int ask(int x)
{
int ans = 0;
while(x < n)
{
ans += step[x];
x = next[x];
}
return ans;
}
void change(int x,int v)
{
num[x] = v;
step[x] = 1;
int r = x - 1,mx = x / M;
int nxt = min(n,x + v);
next[x] = nxt;
if((nxt) / M == mx)
{
step[x] += step[nxt];
next[x] = next[nxt];
}
while((r + 1) % M)
{
nxt = min(n,r + num[r]);
if(nxt / M == mx)
{
step[r] = step[nxt] + 1;
next[r] = next[nxt];
}
r--;
}
return;
}
int q,x,v;
int main()
{
scanf("%d",&n);
for(int i = 0;i < n;i ++)
{
scanf("%d",&num[i]);
next[i] = min(n,i + num[i]);
step[i] = 1;
}
step
= 0;
next
= n + 1;
init();
scanf("%d",&m);
for(int i = 1;i <= m;i ++)
{
scanf("%d",&q);
switch(q)
{
case 1:scanf("%d",&x);printf("%d\n",ask(x));break;
case 2:scanf("%d %d",&x,&v);change(x,v);break;
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: