Wannafly挑战赛16 #E 弹球弹弹弹 splay+基环树+各种思维
链接:https://ac.nowcoder.com/acm/problem/16033
来源:牛客网
有n个位置,标号为1到n的整数,m次操作,第i次操作放置一个弹球在b[i] xor c[i-1]处,并询问b[i] xor c[i-1]处弹球个数c[i]
每次操作后,在x处的弹球被弹到a[x],规定c[0]=0
把球弹来弹去的位置关系刻画出来的话是一个基环树森林的结构.
每个不在环里的点会逐渐走向环,最终循环地在环里不停的转.
然后你发现如果查询不在环上的点可以用一个 $splay$ 来维护每个联通块中每一个 $dep[u]+time[u]$ 的 $dfs$ 序.
其实就是对于每一条链都以连续区间插入,这样查询的时候是区间查询.
然后对于环上的点如何查询什么时候到就自己 $yy$ 一下吧,这个我实在是想不起来了,细节多的要命.
#include<bits/stdc++.h>
#include <unordered_map>
using namespace std;
#define rg register
#define O2 __attribute__((optimize("-O2")))
char *p1,*p2,buf[100000];
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {int x=0; char c=nc(); while(c<48) c=nc(); while(c>47) x=(((x<<2)+x)<<1)+(c^48),c=nc(); return x;}
const int maxn=500003;
const int inf=10000000;
void setIO(string s) {
string in=s+".in";
freopen(in.c_str(),"r",stdin);
freopen("tt.out","w",stdout);
}
struct Splay {
#define lson ch[x][0]
#define rson ch[x][1]
int cnt;
int ch[maxn][2],siz[maxn],f[maxn],mn[maxn],mx[maxn],pos[maxn];
O2 inline void init() {
cnt=0,mx[0]=-inf,mn[0]=inf;
}
O2 inline int get(int x) {
return ch[f[x]][1]==x;
}
O2 inline void pushup(int x) {
siz[x]=siz[lson]+siz[rson]+1;
mx[x]=mn[x]=pos[x];
mx[x]=max(mx[x],mx[rson]);
mn[x]=min(mn[x],mn[lson]);
}
O2 inline void rotate(int x) {
int old=f[x],fold=f[old],which=get(x);
ch[old][which]=ch[x][which^1],f[ch[old][which]]=old;
ch[x][which^1]=old,f[old]=x,f[x]=fold;
if(fold) ch[fold][ch[fold][1]==old]=x;
pushup(old), pushup(x);
}
O2 inline void splay(int x,int &tar) {
int u=f[tar],fa;
for(;(fa=f[x])^u;rotate(x))
if(f[fa]^u)
rotate(get(fa)==get(x)?fa:x);
tar=x;
}
O2 void insert(int &x,int p,int ff) {
if(!x) {
x=++cnt,f[x]=ff,pos[x]=p;
pushup(x);
return;
}
insert(ch[x][p>pos[x]],p,x), pushup(x);
}
O2 int query(int x,int l,int r) {
if(!x||mx[x]<l||mn[x]>r) return 0;
if(mn[x]>=l&&mx[x]<=r) return siz[x];
int re=0;
if(pos[x]>=l&&pos[x]<=r) ++re;
return re+query(lson,l,r)+query(rson,l,r);
}
#undef lson
#undef rson
}tr;
struct Graph {
int edges;
int hd[maxn],to[maxn],nex[maxn];
O2 inline void addedge(int u,int v) {
nex[++edges]=hd[u],hd[u]=edges,to[edges]=v;
}
}G,V;
int oo[maxn];
vector<int>mm[maxn<<1];
vector<int>cir[maxn];
unordered_map<int, vector<int> >ins[maxn];
int n,m,id,tim;
int idx[maxn],dep[maxn],dfn[maxn],st[maxn],ed[maxn],top[maxn],dis[maxn];
unordered_map<int,int>rt[maxn];
unordered_map<int,int>bu[maxn];
namespace prepare {
int du[maxn];
queue<int>Q;
O2 void dfs(int u) {
cir[idx[u]].push_back(u);
for(rg int i=V.hd[u];i;i=V.nex[i])
{
int v=V.to[i];
if(du[v]&&!idx[v]) {
idx[v]=idx[u];
dfs(v);
break;
}
}
}
O2 inline void work() {
for(rg int i=1;i<=V.edges;++i) ++du[V.to[i]];
for(rg int i=1;i<=n;++i) if(!du[i]) Q.push(i);
while(!Q.empty()) {
int u=Q.front(); Q.pop();
for(rg int i=V.hd[u];i;i=V.nex[i]) {
int v=V.to[i];
--du[v];
if(!du[v]) Q.push(v);
}
}
for(rg int i=1;i<=n;++i) {
if(!du[i]) continue;
if(!idx[i]) idx[i]=++id, dfs(i);
}
}
};
O2 void dfs(int u,int ff) {
dep[u]=dep[ff]+1,st[u]=++tim,dfn[tim]=u;
for(rg int i=G.hd[u];i;i=G.nex[i]) {
int v=G.to[i];
if(v==ff||idx[v]) continue;
top[v]=top[u],dfs(v,u);
}
ed[u]=tim;
}
O2 int main() {
// setIO("input");
n=rd();
memset(oo, -1, sizeof(oo));
for(rg int i=1;i<=n;++i) {
int x=rd();
V.addedge(i,x); // 基环树
G.addedge(x,i); // 建树
}
prepare::work(), tr.init();
for(rg int i=1;i<=id;++i)
for(rg int j=0;j<cir[i].size();++j) {
top[cir[i][j]]=cir[i][j],dep[0]=-1,dfs(cir[i][j], 0);
dis[cir[i][j]]=j;
}
m=rd();
int lastans=0;
for(rg int i=0;i<m;++i) {
int b,cur,cur_id,cur_siz;
b=rd(), b^=lastans, lastans=0;
cur_id=idx[top[b]];
cur_siz=cir[cur_id].size();
int x1 = (dis[top[b]] - (i%cur_siz) + cur_siz) % cur_siz;
int x2 = dep[b]%cur_siz;
int tmp = (x1 - x2 + cur_siz) % cur_siz;
ins[cur_id][i+dep[b]].push_back(tmp), mm[i+dep[b]].push_back(cur_id);
for(rg int o=0;o<mm[i].size();++o) {
int uu=mm[i][o];
if(oo[uu]!=i) {
oo[uu]=i;
for(rg int j=0;j<ins[uu][i].size();++j) bu[uu][ins[uu][i][j]]+=1;
}
}
if(idx[b]) lastans+=bu[cur_id][(dis[b]-(i%cur_siz)+cur_siz)%cur_siz];
else {
cur=dep[b]+i;
tr.insert(rt[cur_id][cur], st[b], 0) , tr.splay(tr.cnt, rt[cur_id][cur]);
int a=tr.query(rt[cur_id][cur],st[b],ed[b]);
lastans+=a;
}
printf("%d\n",lastans);
}
return 0;
}
Wannafly挑战赛16 #E 弹球弹弹弹 splay+基环树+各种思维的更多相关文章
- Wannafly 挑战赛16 A 取石子
题目描述 给出四堆石子,石子数分别为a,b,c,d.规定每次只能从堆顶取走石子,问取走所有石子的方案数. 输入描述: 在一行内读入四个由空格分隔的整数a,b,c,d, 输入均为不超过500的正整数 输 ...
- Wannafly挑战赛16
E(pbds) 题意: 1<=m,n<=5e5 分析: 首先指向关系形成了一个基环外向树森林 实际上我们可以完全不用真正的去移动每个球,而只需要在计数的时候考虑考虑就行了 对于树上的情况, ...
- Wannafly挑战赛10 D 小H的询问(线段树)
题目链接 Problem D 这个题类似 SPOJ GSS3 做过那个题之后其实就可以秒掉这题了. 考虑当前线段树维护的结点 在那道题的基础上,这个题要多维护几个东西,大概就是左端点的奇偶性,右端点 ...
- Wannafly挑战赛27 C蓝魔法师
链接Wannafly挑战赛27 C蓝魔法师 给出一棵树,求有多少种删边方案,使得删后的图每个连通块大小小于等于\(k\),\(n,k\leq 2*10^3\) 假设我们正在考虑\(i\)这个子树,那么 ...
- 简单实现弹出弹框页面背景半透明灰,弹框内容可滚动原页面内容不可滚动的效果(JQuery)
弹出弹框 效果展示 实现原理 html结构比较简单,即: <div>遮罩层 <div>弹框</div> </div> 先写覆盖显示窗口的遮罩层div.b ...
- Wannafly挑战赛26-F. msc的棋盘(模型转化+dp)及一类特殊的网络流问题
题目链接 https://www.nowcoder.com/acm/contest/212/F 题解 我们先考虑如果已知了数组 \(\{a_i\}\) 和 \(\{b_i\}\),如何判断其是否合法. ...
- Wannafly 挑战赛 19 参考题解
这一次的 Wannafly 挑战赛题目是我出的,除了第一题,剩余的题目好像对大部分算法竞赛者来说好像都不是特别友好,但是个人感觉题目质量还是过得去的,下面是题目链接以及题解. [题目链接] Wanna ...
- Wannafly挑战赛25游记
Wannafly挑战赛25游记 A - 因子 题目大意: 令\(x=n!(n\le10^{12})\),给定一大于\(1\)的正整数\(p(p\le10000)\)求一个\(k\)使得\(p^k|x\ ...
- Wannafly挑战赛27
Wannafly挑战赛27 我打的第一场$Wannafly$是第25场,$T2$竟然出了一个几何题?而且还把我好不容易升上绿的$Rating$又降回了蓝名...之后再不敢打$Wannafly$了. 由 ...
随机推荐
- Anaconda版本
1. Anaconda各种版本 https://mirrors.tuna.tsinghua.edu.cn/anaconda/archive/ 2. 多个Python环境 conda info -e c ...
- 20191128 Spring Boot官方文档学习(9.10)
9.10.数据库初始化 可以使用不同的方式初始化SQL数据库,具体取决于堆栈是什么.当然,如果数据库是一个单独的进程,您也可以手动执行.建议使用单一机制进行模式生成. 9.10.1.使用JPA初始化数 ...
- window 下python2.7与python3.5两版本共存设置
分别下载两个版本的Python,安装. (1)在Path环境变量中检查以下4个变量(Path中的环境变量是以分号隔开的): 1.c:\Python27 2.c:\Python27\Scripts 3. ...
- 第六周学习总结&(实验报告四)
一.实验目的 (1)掌握类的继承方法 (2)变量的继承和覆盖,方法的继承,重载和覆盖实现 二.实验内容 一.实验目的 (1)掌握类的继承 (2)变量的继承和覆盖,方法的继承,重载和覆盖的实现: 二.实 ...
- Docker之单多/机容器管理
Compose是用于定义和运行多容器Docker应用程序的工具.通过Compose,您可以使用YAML文件来配置应用程序的服务.然后,使用一个命令,就可以从配置中创建并启动所有服务. Docker-C ...
- 17: VUE数据绑定 与 Object.defineProperty
VUE数据绑定原理:https://segmentfault.com/a/1190000006599500?utm_source=tag-newest Object.defineProperty(): ...
- 高效编程之 多线程Event
Event 简介 Event 事件 是线程间通信的最简单方法之一,主要用于线程同步. 处理机制 定义一个全局内置标志Flag,如果Flag为False,执行到 event.wait 时程序就会阻塞,如 ...
- C#多播委托详解
包含多个方法的委托成为多播委托,调用多播委托,可以按照顺序连续调用多个方法,因此,委托的签名就必须返回void;否则,就只能得到委托调用的最好一个方法的结果 1.多播委托可以用运算符"+&q ...
- 网络爬虫之JSOUP
JSOUP中文文档:http://www.open-open.com/jsoup/推荐博客:http://www.cnblogs.com/jycboy/p/jsoupdoc.html 从一个URL加载 ...
- python学习笔记(5)
第七章 模式匹配和正则表达式 1.不用正则表达式来查找文本模式 #对于这样的一个文本查找:3个数字,一个短横线,3个数字,4个端横线,然后再是4个数字,如:415-555-4242def isPh ...