时空限制 2000ms / 128MB
给你一个序列a
每次两个操作:
1.修改x位置的值为y
2.查询区间l,r是否可以重排为值域上连续的一段
输入格式:
第一行两个数n,m
第二行n个数表示a[i]
后面m行每行三个数opt x y,或者opt l r,代表操作
输出格式:
如果可以,输出“damushen”
否则输出“yuanxing”
说明
对于30%的数据,n,m<=500
对于60%的数据,n,m<=100000
对于100%的数据,n,m<=500000
值域1e9
题目分析
lxl的题果然都是神(du)题(liu)
线段树维护区间最大/小值,区间和/平方和
每次查找询问区间的最大小值,检查区间和与平方和是否符合mi~mx的和/平方和
就是hash的思想,另外∑i=1ni2=(2n+1)n(n+1)6\sum_{i=1}^ni^2=\frac{(2n+1)n(n+1)}{6}∑i=1ni2=6(2n+1)n(n+1)
#include<iostream>
#include<cmath>
#include<algorithm>
#include<map>
#include<cstring>
#include<cstdio>
using namespace std;
typedef long long lt;
typedef double dd;
#define sqr(x) ((x)*(x))
lt read()
{
lt f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const lt inf=2e9;
const lt mod=1e9+7;
const int maxn=500010;
int n,m;
lt a[maxn];
lt mi[maxn<<2],mx[maxn<<2];
lt sum[maxn<<2],Sqr[maxn<<2];
void pushup(int p)
{
sum[p]=(sum[p<<1]+sum[p<<1|1])%mod;
Sqr[p]=(Sqr[p<<1]+Sqr[p<<1|1])%mod;
mi[p]=min(mi[p<<1],mi[p<<1|1]);
mx[p]=max(mx[p<<1],mx[p<<1|1]);
}
void build(int s,int t,int p)
{
if(s==t){
mi[p]=mx[p]=sum[p]=a[s];
Sqr[p]=sqr(a[s])%mod;
return;
}
int mid=s+t>>1;
build(s,mid,p<<1);build(mid+1,t,p<<1|1);
pushup(p);
}
void update(int u,int s,int t,int p,lt val)
{
if(s==t){
mi[p]=mx[p]=sum[p]=val;
Sqr[p]=sqr(val)%mod;
return;
}
int mid=s+t>>1;
if(u<=mid) update(u,s,mid,p<<1,val);
else update(u,mid+1,t,p<<1|1,val);
pushup(p);
}
lt qmin(int ll,int rr,int s,int t,int p)
{
if(ll<=s&&t<=rr) return mi[p];
int mid=s+t>>1; lt res=inf;
if(ll<=mid) res=min(res,qmin(ll,rr,s,mid,p<<1));
if(rr>mid) res=min(res,qmin(ll,rr,mid+1,t,p<<1|1));
return res;
}
lt qmax(int ll,int rr,int s,int t,int p)
{
if(ll<=s&&t<=rr) return mx[p];
int mid=s+t>>1; lt res=-inf;
if(ll<=mid) res=max(res,qmax(ll,rr,s,mid,p<<1));
if(rr>mid) res=max(res,qmax(ll,rr,mid+1,t,p<<1|1));
return res;
}
lt qsum(int ll,int rr,int s,int t,int p)
{
if(ll<=s&&t<=rr) return sum[p];
int mid=s+t>>1; lt res=0;
if(ll<=mid) res=(res+qsum(ll,rr,s,mid,p<<1))%mod;
if(rr>mid) res=(res+qsum(ll,rr,mid+1,t,p<<1|1))%mod;
return res;
}
lt qsqr(int ll,int rr,int s,int t,int p)
{
if(ll<=s&&t<=rr) return Sqr[p];
int mid=s+t>>1; lt res=0;
if(ll<=mid) res=(res+qsqr(ll,rr,s,mid,p<<1))%mod;
if(rr>mid) res=(res+qsqr(ll,rr,mid+1,t,p<<1|1))%mod;
return res;
}
lt qpow(lt a,lt k)
{
lt res=1;
while(k>0){
if(k&1) res=(res*a)%mod;
a=(a*a)%mod; k>>=1;
}
return res;
}
lt calc(lt x){ return (x*2+1)%mod*x%mod*(x+1)%mod*qpow(6,mod-2)%mod;}
int main()
{
n=read();m=read();
for(int i=1;i<=n;++i) a[i]=read();
build(1,n,1);
while(m--)
{
int opt=read(),x=read(),y=read();
if(opt==1) update(x,1,n,1,y);
else{
int judge=1;
lt mi=qmin(x,y,1,n,1),mx=qmax(x,y,1,n,1);
if(qsum(x,y,1,n,1)!=(mi+mx)%mod*(mx-mi+1)%mod*qpow(2,mod-2)%mod) judge=0;
else if(qsqr(x,y,1,n,1)!=((calc(mx)-calc(mi-1))%mod+mod)%mod) judge=0;
if(judge) printf("damushen\n");
else printf("yuanxing\n");
}
}
return 0;
}