洛谷 P3792 由乃与大母神原型和偶像崇拜

洛谷 P3792 由乃与大母神原型和偶像崇拜

Problem

糖果屋的故事讲的就是韩赛尔和格雷特被继母赶出家里,因为没饭吃了,然后进了森林发现了一个糖果屋,里面有个女巫,专门吃小孩子

然而如果我们仔细想想这个故事,会发现它没有那么简单

比如说,女巫真的是吃小孩子吗?如果女巫是个善良的老婆婆,无偿救助在森林里面困住的小孩子呢?

还有就是当韩赛尔和格雷特杀死了女巫,回到家中发现她们的继母也死了

这是否意味着她们实际上杀死的是她们的继母?

所以这个故事本质上讲的是她们杀了她们的母亲,也就是打败了大母神

很多神话故事里面都有打败大母神的情节

你看到这里也许已经觉得由乃精神不正常了

然而由乃自从不小心##了自己的##后早就不正常了

由乃研究了很久大母神原型,但是仍然一脸懵逼

于是就出数据结构题骗钱去了

由乃:给你一个序列,每次询问一个区间是否是值域连续段

zzy:你把题意说详细点

由乃:就是说不能有重复数字,比如1 2 2 3就不行,然后4 2 3 1就可以

yql:sb分块

ddd:sb bitset

由乃:woc你们好树链啊,我。。我带修

zzq:#######sb题

由乃:我就是要出原题

给你一个长为\(n\)的序列\(a\)

每次两个操作:

  1. 修改\(x\)位置的值为\(y\)
  2. 查询区间\([l,r]\)否可以重排为值域上连续的一段

如果可以,输出“damushen”

否则输出“yuanxing”

对于\(100\%\)的数据,\(n,m \le 500000\)

初始值的值域小于\(2.5\times 10^7\),修改操作的\(y\)小于等于\(n\)

Solution

没有想到什么正解(其实是我不会证),但是可以用区间\(hash\)的思想。

请问,给你一段数字的某些特征信息,如何得之,它是不是连续值域段?

既然是值域连续段,那么首先就要值域等于其极差+1:

  • \(len=max-min+1\)

这里我们需要维护\(max\)\(min\).

然后呢,这一段当然是个公差为1的等差数列,当然满足等差数列的求和公式:

  • \(sum=(min+max)*(max-min+1)/2\)

这里我们要维护\(sum\).

再然后呢,是不是还有点不放心?我们再维护一个区间平方和(记为\(pow2\)好了)。这里要先知道,\(\sum_{i=1}^ni^2=\frac n6\times(n+1)\times(2\times n+1)\).这是一个前缀和的形式,使用的时候差分即可。

\[pow2=\frac{max}{6}\times(max+1)\times(2\times max+1)-\frac{min-1}{6}\times min\times(2\times min-1) \]

到这里,已经可以AC这道题啦!但是如果还是不放心,可以再维护一个立方和(记为\(cub\))。使用公式\(\sum_{i=1}^ni^3=(\sum_{i=1}^ni)^2=\frac{(1+n)^2\times n^2}4\).同上差分即可。

欸?这个数字这么大,会不会溢出?

我这里用\(\text{unsigned long long}\)自然溢出。当然您也可以取模(但是有点慢)。

注意,在模意义下就不能用除法了。但是可以将除法移到等式的另一边去就变成了乘法,可以愉快的比较啦!

Code

/**************************************************************
 * Problem: 3792
 * Author: Vanilla_chan
 * Date: 20210321
 * E-Mail: Vanilla_chan@outlook.com
**************************************************************/
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<string>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<queue>
#include<vector>
#include<limits.h>
#define IL inline
#define re register
#define LL unsigned long long
#define ULL unsigned long long
//#define int ULL
#ifdef TH
#define debug printf("Now is %d\n",__LINE__);
#else
#define debug 
#endif
#ifdef ONLINE_JUDGE
char buf[1<<23],* p1=buf,* p2=buf,obuf[1<<23],* O=obuf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
#endif
using namespace std;

namespace oi
{
	inline bool isdigit(const char& ch)
	{
		return ch<='9'&&ch>='0';
	}
	inline bool isalnum(const char& ch)
	{
		return (ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9');
	}
	struct istream
	{
		char ch;
		bool fu;
		template<class T>inline istream& operator>>(T& d)
		{
			fu=d=0;
			while(!isdigit(ch)&&ch!='-') ch=getchar();
			if(ch=='-') fu=1,ch=getchar();
			d=ch-'0';ch=getchar();
			while(isdigit(ch))
				d=(d<<3)+(d<<1)+(ch^'0'),ch=getchar();
			if(fu) d=-d;
			return *this;
		}
		inline istream& operator>>(string& str)
		{
			str.clear();
			for(;!isdigit(ch);ch=getchar());
			while(isalnum(ch))
				str+=ch,ch=getchar();
			return *this;
		}
	}cin;
	inline int read()
	{
		int x=0,fu=1;
		char ch=getchar();
		while(!isdigit(ch)&&ch!='-') ch=getchar();
		if(ch=='-') fu=-1,ch=getchar();
		x=ch-'0';ch=getchar();
		while(isdigit(ch)) { x=x*10+ch-'0';ch=getchar(); }
		return x*fu;
	}
	int G[55];
	template<class T>inline void write(T x)
	{
		int g=0;
		if(x<0) x=-x,putchar('-');
		do { G[++g]=x%10;x/=10; } while(x);
		for(int i=g;i>=1;--i)putchar('0'+G[i]);putchar('\n');
	}
};
using namespace oi;
#define N 500010
int n,m;
int a[N];
struct node
{
	int l,r,mx,mn;
	ULL sum,pow2,cub;
#define l(x) b[x].l
#define r(x) b[x].r
#define mx(x) b[x].mx
#define mn(x) b[x].mn
#define sum(x) b[x].sum
#define pow2(x) b[x].pow2
#define cub(x) b[x].cub
}b[N*4];
void upd(int p)
{
	mx(p)=max(mx(p<<1),mx(p<<1|1));
	mn(p)=min(mn(p<<1),mn(p<<1|1));
	sum(p)=sum(p<<1)+sum(p<<1|1);
	pow2(p)=pow2(p<<1)+pow2(p<<1|1);
	cub(p)=cub(p<<1)+cub(p<<1|1);
}
void build(int p,int l,int r)
{
	l(p)=l;
	r(p)=r;
	if(l==r)
	{
		cub(p)=pow2(p)=sum(p)=mx(p)=mn(p)=a[l];
		pow2(p)*=pow2(p);
		cub(p)*=pow2(p);
		return;
	}
	int mid=l+r>>1;
	build(p<<1,l,mid);
	build(p<<1|1,mid+1,r);
	upd(p);
}
void change(int p,int x,int k)
{
	if(l(p)==r(p))
	{
		cub(p)=pow2(p)=sum(p)=mx(p)=mn(p)=a[x]=k;
		pow2(p)*=pow2(p);
		cub(p)*=pow2(p);
		return;
	}
	int mid=l(p)+r(p)>>1;
	if(x<=mid) change(p<<1,x,k);
	else change(p<<1|1,x,k);
	upd(p);
}
int ask_mx(int p,int l,int r)
{
	if(l<=l(p)&&r(p)<=r)
	{
		return mx(p);
	}
	int mid=l(p)+r(p)>>1;
	if(r<=mid) return ask_mx(p<<1,l,r);
	if(l>mid) return ask_mx(p<<1|1,l,r);
	return max(ask_mx(p<<1,l,r),ask_mx(p<<1|1,l,r));
}
int ask_mn(int p,int l,int r)
{
	if(l<=l(p)&&r(p)<=r)
	{
		return mn(p);
	}
	int mid=l(p)+r(p)>>1;
	if(r<=mid) return ask_mn(p<<1,l,r);
	if(l>mid) return ask_mn(p<<1|1,l,r);
	return min(ask_mn(p<<1,l,r),ask_mn(p<<1|1,l,r));
}
ULL ask_sum(int p,int l,int r)
{
	if(l<=l(p)&&r(p)<=r)
	{
		return sum(p);
	}
	int mid=l(p)+r(p)>>1;
	if(r<=mid) return ask_sum(p<<1,l,r);
	if(l>mid) return ask_sum(p<<1|1,l,r);
	return ask_sum(p<<1,l,r)+ask_sum(p<<1|1,l,r);
}
ULL ask_pow(int p,int l,int r)
{
	if(l<=l(p)&&r(p)<=r)
	{
		return pow2(p);
	}
	int mid=l(p)+r(p)>>1;
	if(r<=mid) return ask_pow(p<<1,l,r);
	if(l>mid) return ask_pow(p<<1|1,l,r);
	return ask_pow(p<<1,l,r)+ask_pow(p<<1|1,l,r);
}
ULL ask_cub(int p,int l,int r)
{
	if(l<=l(p)&&r(p)<=r)
	{
		return cub(p);
	}
	int mid=l(p)+r(p)>>1;
	if(r<=mid) return ask_cub(p<<1,l,r);
	if(l>mid) return ask_cub(p<<1|1,l,r);
	return ask_cub(p<<1,l,r)+ask_cub(p<<1|1,l,r);
}
ULL mx,mn;
ULL sum;
signed main()
{
	//freopen(".in","r",stdin);
	//freopen(".out","w",stdout);
	n=read();
	m=read();
	for(int i=1;i<=n;i++) a[i]=read();
	build(1,1,n);
	int l,r,op;
	while(m--)
	{
		op=read();
		l=read();
		r=read();
		if(op==1)
		{
			change(1,l,r);
		}
		else
		{
			mx=ask_mx(1,l,r);
			mn=ask_mn(1,l,r);
			if(mx-mn!=r-l)
			{
				cout<<"yuanxing"<<endl;
				continue;
			}
			if(ask_sum(1,l,r)*2!=(mn+mx)*(mx-mn+1))
			{
				cout<<"yuanxing"<<endl;
				continue;
			}
			if(ask_pow(1,l,r)*6!=(mx*(mx+1)*(2*mx+1))-(mn*(mn-1)*(2*mn-1)))
			{
				cout<<"yuanxing"<<endl;
				continue;
			}
			if(ask_cub(1,l,r)*4!=(1+mx)*(1+mx)*mx*mx-mn*mn*(mn-1)*(mn-1))
			{
				cout<<"yuanxing"<<endl;
				continue;
			}
			cout<<"damushen"<<endl;
		}
	}
	return 0;
}

如果不要立方和的判断的话可以稳过。

加上立方和,稍有些不稳定(或者说是洛谷评测姬不稳定?)。

posted @ 2021-03-22 14:58  Vanilla_chan  阅读(106)  评论(0编辑  收藏  举报