传送门
解析:
数组开小TLE了若干次 (在线丢人)
其实想法还是很简单的,考虑离散化,为了保证离散化前不连续的值离散化后也不连续,我们将每个每个值+1放进数组中。
给每个值赋上一个随机值,然后树状数组维护前缀和,前缀异或和。
每个修改直接在树状数组里面修改。
询问先查询区间和,求出值域连续情况下的左右端点,然后看一下区间异或和和原值域上异或和是否相等。
代码(不要问我为什么unsigned long long 用 u32 来 typedef):
#include<bits/stdc++.h>
#define ll long long
#define re register
#define gc get_char
#define cs const
namespace IO{
inline char get_char(){
static cs int Rlen=1<<20|1;
static char buf[Rlen],*p1,*p2;
return (p1==p2)&&(p2=(p1=buf)+fread(buf,1,Rlen,stdin),p1==p2)?EOF:*p1++;
}
inline int getint(){
re char c;
while(!isdigit(c=gc()));re int num=c^48;
while(isdigit(c=gc()))num=(num+(num<<2)<<1)+(c^48);
return num;
}
}
using namespace IO;
using std::cout;
using std::cerr;
typedef unsigned ll u32;
cs int N=5e5+5;
int n,m;
int a[N],b[N<<2],len;
struct Opt{
int typ,x,y;
}opt[N];
std::mt19937 R(19491001);
u32 p[N<<2],pre[N<<2],sum[N],xsum[N];
inline void adds(int pos,int val){
for(;pos<=n;pos+=pos&-pos)sum[pos]+=val;
}
inline u32 querys(int pos){
u32 res=0;
for(;pos>0;pos^=pos&-pos)res+=sum[pos];
return res;
}
inline void addx(int pos,u32 val){
for(;pos<=n;pos+=pos&-pos)xsum[pos]^=val;
}
inline u32 queryx(int pos){
u32 res=0;
for(;pos>0;pos^=pos&-pos)res^=xsum[pos];
return res;
}
signed main(){
n=getint(),m=getint();
for(int re i=1;i<=n;++i){
a[i]=getint();
b[++len]=a[i];
b[++len]=a[i]+1;
}
for(int re i=1;i<=m;++i){
opt[i].typ=getint();
opt[i].x=getint();
opt[i].y=getint();
if(opt[i].typ==1){
b[++len]=opt[i].y;
b[++len]=opt[i].y+1;
}
}
std::sort(b+1,b+len+1);
len=std::unique(b+1,b+len+1)-b-1;
for(int re i=1;i<=n;++i)a[i]=std::lower_bound(b+1,b+len+1,a[i])-b;
for(int re i=1;i<=m;++i)if(opt[i].typ==1)opt[i].y=std::lower_bound(b+1,b+len+1,opt[i].y)-b;
for(int re i=1;i<=len;++i){
p[i]=((unsigned ll)R()<<32)^R();
pre[i]=pre[i-1]^p[i];
}
for(int re i=1;i<=n;++i){
adds(i,a[i]);
addx(i,p[a[i]]);
}
for(int re i=1;i<=m;++i)switch(opt[i].typ){
case 1:{
adds(opt[i].x,opt[i].y-a[opt[i].x]);
addx(opt[i].x,p[opt[i].y]^p[a[opt[i].x]]);
a[opt[i].x]=opt[i].y;
break;
}
case 2:{
int mid=(querys(opt[i].y)-querys(opt[i].x-1))/(opt[i].y-opt[i].x+1);
int l=mid-(opt[i].y-opt[i].x)/2;
int r=l+opt[i].y-opt[i].x;
if(l<=0||r>len)puts("yuanxing");
else if((queryx(opt[i].y)^queryx(opt[i].x-1))==(pre[r]^pre[l-1]))puts("damushen");
else puts("yuanxing");
break;
}
}
return 0;
}