首页 > 其他分享 >[Ynoi2013]大学

[Ynoi2013]大学

时间:2022-12-14 21:58:54浏览次数:78  
标签:tmp return int Ynoi2013 tree 大学 data op

链接:https://www.luogu.com.cn/problem/P5610

题目描述:给定一个长为\(n\)的序列\(a\),支持区间为\(d\)倍数的除以\(d\)的操作,以及区间查询和的操作,强制在线。

题解:可以发现颜色均摊。

所以我们就是要求区间为\(d\)倍数是哪一些。我们可以朝着暴力的做法想,将所有点插入至其约数集合,然后查询\([l,r]\)的点即可。

但\(set\)不支持整体建树,所以我们要开\(500000\)个平衡树维护,当然要整体的分治建树。

可以发现只支持平衡树单点删除与查询,所以\(treap\)可以不需要旋转。

当然这题有个更简单的做法,可以用并查集替代平衡树,然后删除就将\(x\)想\(pv_{x}\)合并,这样就可以查到合法元素,然后这样做复杂度显著降低。

#include<iostream>
#include<cstdio>
#include<vector>
using namespace std;
struct node
{
	int l,r,data;
};
node tree[20000001];
long long n,top,res,a[500001];
long long c[500001];
int rt[500001];
vector<int>p[500001];
int lowbit(int x)
{
	return x&(-x);
}
void add(int x,int d)
{
	for (;x<=n;x+=lowbit(x))
		c[x]+=d;
	return;
}
long long sum(int x)
{
	res=0;
	for (;x>=1;x-=lowbit(x))
		res+=c[x];
	return res;
}
int new_node(int x)
{
	tree[++top].data=x;
	return top;
}
int build_tree(int op,int l,int r)
{
	if (l>r)
		return 0;
	int mid=(l+r)/2;
	int P=new_node(p[op][mid]);
	tree[P].l=build_tree(op,l,mid-1);
	tree[P].r=build_tree(op,mid+1,r);
	tree[P].data=p[op][mid]; 
	return P;
}
int nxt(int &k)
{
	if (tree[k].l)
		return nxt(tree[k].l);
	int tmp=tree[k].data;
	k=tree[k].r;
	return tmp;
}
void del(int &k)
{
	int tmp;
	if (tree[k].r)
	{
		tmp=nxt(tree[k].r);
		tree[k].data=tmp;
	}
	else
		k=tree[k].l;
}
int find(int op,int &k,int l,int r)
{
	if (k==0)
		return 0;
	int tmp;
	if (tree[k].data>=l)
	{
		if (tmp=find(op,tree[k].l,l,r))
			return tmp;
		if (tree[k].data<=r)
		{
			if (a[tree[k].data]%op==0)
			{
				add(tree[k].data,-a[tree[k].data]);
				a[tree[k].data]/=op;
				add(tree[k].data,a[tree[k].data]);
			}
			tmp=tree[k].data;
			if (a[tree[k].data]%op!=0)
				del(k);
			return tmp;
		}
		return 0;
	}
	else
		return find(op,tree[k].r,l,r);
}
long long read()
{
	char c=0;
	long long sum=0;
	while (c<'0'||c>'9')
		c=getchar();
	while ('0'<=c&&c<='9')
	{
		sum=sum*10+c-'0';
		c=getchar();
	}
	return sum;
}
signed main()
{
	long long q,op,l,r,x,tmp,lst,ans=0;
	n=read(),q=read();
	for (int i=1;i<=n;++i)
	{
		a[i]=read();
		add(i,a[i]);
		for (int j=2;j*j<=a[i];++j)
			if (a[i]%j==0)
			{
				p[j].push_back(i);
				if (j*j!=a[i])
					p[a[i]/j].push_back(i);
			}
		p[a[i]].push_back(i); 
	}
	for (int i=2;i<=5e5;++i)
		rt[i]=build_tree(i,0,p[i].size()-1);
	while (q--)
	{
		op=read(),l=lst=read(),r=read();
		l^=ans;
        lst^=ans;
		r^=ans;
		if (op==1)
		{
			x=read();
			x^=ans;
			if (x!=1)
				while (tmp=find(x,rt[x],lst,r))
					lst=tmp+1;
		}
		else
		{
			ans=sum(r)-sum(l-1);
			printf("%lld\n",ans);
		}
	}
	return 0;
}

标签:tmp,return,int,Ynoi2013,tree,大学,data,op
From: https://www.cnblogs.com/zhouhuanyi/p/16983695.html

相关文章