P3792 由乃与大母神原型和偶像崇拜
给你一个序列a
每次两个操作:
1.修改x位置的值为y
2.查询区间l,r是否可以重排为值域上连续的一段
输入输出格式
输入格式:
第一行两个数n,m
第二行n个数表示a[i]
后面m行每行三个数opt x y,或者opt l r,代表操作
输出格式:
如果可以,输出“damushen”
否则输出“yuanxing”
输入输出样例
输入样例#1:
复制
5 5 1 2 3 4 5 2 1 5 2 2 3 2 3 3 1 3 6 2 3 5
输出样例#1: 复制
damushen damushen damushen damushen
说明
对于30%的数据,n,m<=500
对于60%的数据,n,m<=100000
对于100%的数据,n,m<=500000
值域1e9
2s
这道题主要是要知道一个用平方和来体现哈希的思想。
那就是在区间中最小值到最大值的平方之和是唯一的(立方和一样)。
于是我们就可以用线段树保存区间最大值,最小值和平方和,来进行操作。
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<algorithm> #define ll long long #define il inline #define db double #define max(a,b) ((a>b)?(a):(b)) #define min(a,b) ((a<b)?(a):(b)) using namespace std; il int gi() { int x=0,y=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-') y=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*y; } int a[500005],tmax[2000005],tmin[2000005],tsum[2000005]; il void build(int rt,int l,int r) { if(l==r) { tmax[rt]=tmin[rt]=a[l]; tsum[rt]=a[l]*a[l]; return; } int m=(l+r)>>1; build(rt<<1,l,m); build(rt<<1|1,m+1,r); tmax[rt]=max(tmax[rt<<1],tmax[rt<<1|1]); tmin[rt]=min(tmin[rt<<1],tmin[rt<<1|1]); tsum[rt]=tsum[rt<<1]+tsum[rt<<1|1]; } il int querymax(int rt,int l,int r,int L,int R) { if(L<=l&&R>=r) return tmax[rt]; int m=(l+r)>>1,r1=-1e9,r2=-1e9; if(L<=m) r1=querymax(rt<<1,l,m,L,R); if(m<R) r2=querymax(rt<<1|1,m+1,r,L,R); return max(r1,r2); } il int querymin(int rt,int l,int r,int L,int R) { if(L<=l&&R>=r) return tmin[rt]; int m=(l+r)>>1,r1=1e9,r2=1e9; if(m>=L) r1=querymin(rt<<1,l,m,L,R); if(m<R) r2=querymin(rt<<1|1,m+1,r,L,R); return min(r1,r2); } il int querysum(int rt,int l,int r,int L,int R) { if(L<=l&&R>=r) return tsum[rt]; int m=(l+r)>>1,s=0; if(m>=L) s+=querysum(rt<<1,l,m,L,R); if(m<R) s+=querysum(rt<<1|1,m+1,r,L,R); return s; } il void update(int rt,int l,int r,int pos,int v) { if(l==r) { tmax[rt]=v; tmin[rt]=v; tsum[rt]=v*v; return; } int m=(r+l)>>1; if(pos<=m) update(rt<<1,l,m,pos,v); else update(rt<<1|1,m+1,r,pos,v); tmax[rt]=max(tmax[rt<<1],tmax[rt<<1|1]); tmin[rt]=min(tmin[rt<<1],tmin[rt<<1|1]); tsum[rt]=tsum[rt<<1]+tsum[rt<<1|1]; } il int he(int x,int y) { int s=0; for(int i=x;i<=y;i++) s+=i*i; return s; } int main() { memset(tmin,127/3,sizeof(tmin)); int n=gi(),m=gi(),l,r,minx,maxn,sum,vis; for(int i=1;i<=n;i++) a[i]=gi(); build(1,1,n); for(int i=1;i<=m;i++) { vis=gi(),l=gi(),r=gi(); if(vis==2) { minx=querymin(1,1,n,l,r); maxn=querymax(1,1,n,l,r); sum=querysum(1,1,n,l,r); if(maxn-minx!=r-l) { printf("yuanxing\n"); continue; } if(he(minx,maxn)==sum) printf("damushen\n"); else printf("yuanxing\n"); } else update(1,1,n,l,r); } return 0; }
PEACE