博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
题解 洛谷P3203/BZOJ2002【[HNOI2010]弹飞绵羊】
阅读量:4635 次
发布时间:2019-06-09

本文共 2440 字,大约阅读时间需要 8 分钟。

裸的LCT,关键是要怎么连边,怎么将这种弹飞关系转化成连边就行了。

那么我们可以这样连边:

  • 一个节点i的爸爸就是i+ki。

  • 没有i+ki那么就被弹飞了,即\(i\)的爸爸是虚拟节点n+1。

那么怎么求次数呢?

  • i的深度就是次数

对于求深度,我们可以先将x弄成root,然后通过Access(n+1)n+1号节点和x节点丢到一个Splay里面,维护一个size,每次询问的answer就是已经Splay到根的n+1号节点的size了。

Code:

#include
#define ll long long#define inf 0x3f3f3f3f#define RI register intusing namespace std;const int N=2e5+2;template
inline void IN(Tp &x){ int f=1;x=0;char ch=getchar(); while(ch<'0'||ch>'9')if(ch=='-')f=-1,ch=getchar(); while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();x*=f;}int f[N],s[N],r[N],val[N],hep[N],ch[N][2];inline int get(int x){return ch[f[x]][0]==x||ch[f[x]][1]==x;}inline void pushup(int x){s[x]=s[ch[x][0]]+s[ch[x][1]]+1;} inline void pushdown(int x){ if(!r[x])return;r[x]=0; swap(ch[x][0],ch[x][1]); if(ch[x][0])r[ch[x][0]]^=1; if(ch[x][1])r[ch[x][1]]^=1;}inline void rotate(int x){ int y=f[x],z=f[y],k=ch[y][1]==x,v=ch[x][!k]; if(get(y))ch[z][ch[z][1]==y]=x;ch[x][!k]=y,ch[y][k]=v; if(v)f[v]=y;f[y]=x,f[x]=z;pushup(y),pushup(x); } inline void Splay(int x){ int y=x,top=0;hep[++top]=y; while(get(y))hep[++top]=y=f[y]; while(top)pushdown(hep[top--]); while(get(x)){ y=f[x],top=f[y]; if(get(y)) rotate((ch[y][0]==x)^(ch[top][0]==y)?x:y); rotate(x); }pushup(x);return;}inline void Access(int x){ for(register int y=0;x;x=f[y=x]) Splay(x),ch[x][1]=y,pushup(x);}inline int findroot(int x){ Access(x);Splay(x); while(ch[x][0])pushdown(x),x=ch[x][0]; return x;}inline void makeroot(int x){Access(x);Splay(x);r[x]^=1;}inline void split(int x,int y){makeroot(x);Access(y);Splay(y);} inline void link(int x,int y){makeroot(x);if(findroot(y)!=x)f[x]=y;}inline void cut(int x,int y){ split(x,y);if(findroot(y)==x&&f[x]==y&&!ch[x][1]) {f[x]=ch[y][0]=0;pushup(y);}return;}int n,m;int main(){ scanf("%d",&n); for(register int i=1;i<=n+1;++i)s[i]=1; for(register int x,i=1;i<=n;++i){ scanf("%d",&x);val[i]=x; link(i,(i+x<=n)?i+x:n+1); }scanf("%d",&m); for(register int op,x,y,i=1;i<=m;++i){ scanf("%d%d",&op,&x);++x; if(op==1){ makeroot(x);Access(n+1);Splay(n+1); printf("%d\n",s[n+1]-1); }else if(op==2){ scanf("%d\n",&y); cut(x,(x+val[x]<=n)?x+val[x]:n+1); link(x,(x+y<=n)?x+y:n+1);val[x]=y; } }return 0;}

所以就没了。

转载于:https://www.cnblogs.com/K-Qiuly/p/10263185.html

你可能感兴趣的文章
lua单链表实现
查看>>
MySql按日期进行统计(前一天、本周、某一天)[转载]
查看>>
经常用得到的安卓数据库基类
查看>>
大智慧面试经验
查看>>
比特币脚本及交易分析 - 智能合约雏形
查看>>
kafka消息会不会丢失
查看>>
codeforces-1132 (div2)
查看>>
简单入门dos程序
查看>>
linux下occi操作oracle数据库,中文乱码的问题
查看>>
JS原型与原型链
查看>>
SVG.js 笔记 (一)
查看>>
struts2笔记01-环境搭建
查看>>
appium 控件定位
查看>>
oracle sql 获取本季度所有月份,上季度所有月份
查看>>
VUE的组件DEMO
查看>>
xshell连接Linux、ngix部署
查看>>
XCODE 6.1.1 配置GLFW
查看>>
vue element 关闭当前tab 跳转到上一路由
查看>>
4、面向对象
查看>>
[NOI2005]聪聪与可可(期望dp)
查看>>