列表

详情


NC16033. 弹球弹弹弹

描述

有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

输入描述

第一行一个整数n
接下来n行每行一个整数,表示序列a
接下来一行一个整数m
接下来m行每行一个整数,表示序列b

输出描述

m行,每行一个整数,表示序列c

示例1

输入:

6
1
2
1
3
3
6
5
1
4
7
3
7

输出:

1
1
1
1
2

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 1814ms, 内存消耗: 184288K, 提交时间: 2018-05-25 21:29:06

#include<bits/stdc++.h>
using namespace std;

#define rep(i,l,r) for(int i=l;i<=r;++i)
const int N=5e5+5;
int n;
int lk[N];vector<int>son[N];
int belong[N],id[N],deep[N],dfn[N],sz[N];
int ccnt,fir[N],len[N],s[N],tot;
#define mid ((l+r)/2)
namespace SEG
{
const int T=N*20+N+N+N;
int cl[T],cr[T],s[T],tot=N+N;
void add(int k,int x)
{
	int l=1,r=n;
	while(1)
	{
		++s[k];
		if(l==r)break;
		if(x<=mid)
		{
			k=cl[k]?cl[k]:cl[k]=++tot;
			r=mid;
		}
		else
		{
			k=cr[k]?cr[k]:cr[k]=++tot;
			l=mid+1;
		}
	}
}
int ans,ql,qr;
void dfs(int k,int l,int r)
{
	if(!s[k])return ;
	if(ql<=l&&qr>=r)
	{
		ans+=s[k];
		return ;
	}
	if(ql<=mid)dfs(cl[k],l,mid);
	if(qr>mid)dfs(cr[k],mid+1,r);
}
int qiu(int k,int l,int r)
{
	ans=0;ql=l;qr=r;
	dfs(k,1,n);
	return ans;
}
};
namespace DFS
{
int tot;
void dfs(int x,int no,int dep)
{
	belong[x]=ccnt;
	deep[x]=dep;id[x]=::tot;
	dfn[x]=++tot;
	sz[x]=1;
	for(auto y:son[x])
	if(y!=no)
	{
		dfs(y,0,dep+1);
		sz[x]+=sz[y];
	}
}
};
void init(int x)
{
	++ccnt;
	while(!belong[x])
	{
		belong[x]=ccnt;
		x=lk[x];
	}
	fir[ccnt]=tot;
	for(int y=lk[x],last=x;;last=y,y=lk[y])
	{
		DFS::dfs(y,last,1);
		++tot;
		if(y==x)break;
	}
	len[ccnt]=tot-fir[ccnt];
}
vector<int>lkq[N];

int main()
{
	//eopen("1.in","r",stdin);
	cin>>n;
	rep(i,1,n)
	{
		scanf("%d",lk+i);
		son[lk[i]].push_back(i);
	}
	rep(x,1,n)
	if(!belong[x])
	{
	//	cerr<<"x="<<x<<endl;
		init(x);
	}
	int m;cin>>m;
	int last=0;
	rep(i,1,m)
	{
		int x;
		scanf("%d",&x);
		x^=last;
		//cerr<<"x="<<x<<endl;
		SEG::add(deep[x]+i,dfn[x]);
		if(i+deep[x]<=m)lkq[i+deep[x]].push_back(x);
		
		for(auto x:lkq[i])
		{
			int b=belong[x];
			++s[fir[b]+(id[x]-fir[b]+len[b]-(i-1)%len[b])%len[b]];
		}
		int b=belong[x];
		last=0;
		if(deep[x]==1)
		last=s[fir[b]+(id[x]-fir[b]+len[b]-i%len[b])%len[b]];
		last+=SEG::qiu(deep[x]+i,dfn[x],dfn[x]+sz[x]-1);
		printf("%d\n",last);
	}
}

C++11(clang++ 3.9) 解法, 执行用时: 1043ms, 内存消耗: 27112K, 提交时间: 2018-05-25 22:02:10

#include<stdio.h>
#include<bits/stdc++.h>
#define F(i,l,r) for(int i=l;i<=r;++i)
const int N=1e6+7;
int _(){
	int x=0,c=getchar();
	while(c<48)c=getchar();
	while(c>47)x=x*10+c-48,c=getchar();
	return x;
}
int n,m,t,la;
int fa[N],in[N],q[N],ql=0,qr=0,c[N],c0[N],ws[N],e0[N],nx[N];
int sz[N],son[N],top[N],len[N],id[N],idp=0,ss[N];
void ins(int i){
	int w=ws[i],z=top[w],d=t+id[w]-id[z];
	++c[c0[i]=id[z]+d%len[z]];
	if(!in[z]&&++d<=m)ws[i]=fa[z],nx[i]=e0[d],e0[d]=i;
}
int que(int w){
	int z=top[w];
	return c[id[z]+(t+id[w]-id[z])%len[z]];
}
int main(){
	n=_();
	assert(1<=n&&n<=500000);
	F(i,1,n)++in[fa[i]=_()],assert(1<=fa[i]&&fa[i]<=n);
	F(i,1,n)if(!in[i])sz[q[++qr]=i]=1;
	while(ql!=qr){
		int w=q[++ql],f=fa[w];
		sz[f]+=sz[w];
		if(sz[w]>sz[son[f]])son[f]=w;
		if(!--in[f])q[++qr]=f;
	}
	for(int i=qr,w;i;--i)if(!top[w=q[i]]){
		for(int u=w;u;u=son[u])top[u]=w,id[u]=++idp;
		len[w]=idp-id[w]+1;
	}
	F(w,1,n)if(in[w]==1){
		int sp=0;
		for(int u=fa[w];in[u]==1;in[u]=2,u=fa[u])top[u]=w,ss[++sp]=u;
		for(len[w]=sp;sp;id[ss[sp--]]=++idp);
	}
	for(m=_(),t=1,assert(1<=m&&m<=500000);t<=m;++t){
		for(int i=e0[t],j;i;j=nx[i],--c[c0[i]],ins(i),i=j);
		int w=ws[t]=_()^la;
		assert(1<=w&&w<=n);
		ins(t);
		printf("%d\n",la=que(w));
//		la=0;
	}
	return 0;
}

上一题