Luogu3792 由乃与大母神原型和偶像崇拜

原题链接:https://www.luogu.com.cn/problem/P3792

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

(精简版题面,想看原题面的读者可以点击上方链接)

题目描述

给你一个长为 n n n 的序列 a a a

每次两个操作:

修改 x x x 位置的值为 y y y

查询区间 [ l , r ] [l,r] [l,r] 是否可以重排为值域上连续的一段

输入格式

第一行两个数 n , m n,m nm

第二行 n n n 个数表示 a i a_i ai

后面 m m m 行每行三个数 o p t opt opt x x x y y y,或者 o p t opt opt l l l r r r,代表操作

输出格式

如果可以,输出“damushen”

否则输出“yuanxing”

输入输出样例

输入 #1
5 5
1 2 3 4 5
2 1 5
2 2 3
2 3 3
1 3 4
2 3 5
输出 #1
damushen
damushen
damushen
yuanxing

说明/提示

对于 30 % 30\% 30% 的数据, n , m ≤ 500 n,m \le 500 n,m500

对于 60 % 60\% 60% 的数据, n , m ≤ 100000 n,m \le 100000 n,m100000

对于 100 % 100\% 100% 的数据, n , m ≤ 500000 n,m \le 500000 n,m500000

初始值的值域小于 2.5 × 1 0 7 2.5\times 10^7 2.5×107 ,修改操作的 y y y 小于等于 n n n

2s

题解

先吐槽一下这题面太长了,dark不B。

运用了哈希的思想,对于两串数列,如果最小值、最大值以及平方和都一样,那么这两串数列里的数很可能是一样的。所以我们用线段树维护最小/大值和平方和,询问时通过区间的最小/大值算出如果是连续值域的话平方和是多少,与实际求得的平方和对比即可。

如果只算平方和不放心,还可以有和、立方和等任君挑选,另外,一个好的模数可以让编程工作事半功倍。

不过数据好像挺水,之前骗分写的只能合并已经是连续值域区间的线段树都能A掉前三个点和第十一个hack数据。

代码

这个模数是真滴强

注意因为是取模运算,平方数列和公式中的 ÷ 6 \div 6 ÷6不能使用,应该移项变成 × 6 \times 6 ×6

#include<bits/stdc++.h>
#define ls v<<1
#define rs v<<1|1
#define sqr(x) 1ll*(x)*(x+1)%mod*(2*(x)+1)%mod
using namespace std;
const int M=5e5+5,mod=19260817;
struct node{
    
    int mn,mx,sum;}tree[M<<2];
int n,m,a[M];
node up(node a,node b){
    
    return (node){
    
    min(a.mn,b.mn),max(a.mx,b.mx),(a.sum+b.sum)%mod};}
void build(int v,int le,int ri)
{
    
    
    if(le==ri){
    
    tree[v].mn=tree[v].mx=a[le],tree[v].sum=1ll*a[le]*a[le]%mod;return;}
    int mid=le+ri>>1;
    build(ls,le,mid);build(rs,mid+1,ri);
    tree[v]=up(tree[ls],tree[rs]);
}
void modify(int v,int le,int ri,int x,int val)
{
    
    
    if(le==ri){
    
    tree[v].mn=tree[v].mx=val,tree[v].sum=1ll*val*val%mod;return;}
    int mid=le+ri>>1;
    if(x<=mid)modify(ls,le,mid,x,val);
    else modify(rs,mid+1,ri,x,val);
    tree[v]=up(tree[ls],tree[rs]);
}
node ask(int v,int le,int ri,int ll,int rr)
{
    
    
    if(ll<=le&&ri<=rr)return tree[v];
    int mid=le+ri>>1;
    node r=(node){
    
    INT_MAX,-INT_MAX,0};
    if(ll<=mid)r=ask(ls,le,mid,ll,rr);
    if(mid<rr)r=up(r,ask(rs,mid+1,ri,ll,rr));
    return r;
}
void in()
{
    
    
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i)scanf("%d",&a[i]);
}
void ac()
{
    
    
    build(1,1,n);
    node r;
    for(int op,a,b;m--;)
    {
    
    
        scanf("%d%d%d",&op,&a,&b);
        if(op-1)
        {
    
    
            r=ask(1,1,n,a,b);
            puts(6ll*r.sum%mod==(sqr(r.mx)-sqr(r.mn-1)+mod)%mod?"damushen":"yuanxing");
        }
        else modify(1,1,n,a,b);
    }
}
int main()
{
    
    
    in(),ac();
    system("pause");
}

猜你喜欢

转载自blog.csdn.net/ShadyPi/article/details/113914309