yiwei

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

题意

给定长为 \(n\) 的数组 \(a\),支持单点修改,\(q\) 次查询区间 \([l,r]\) 是否可以重排为值域上连续的一段。

\(n,q\le5\times10^5,a_i\le2.5\times10^7\) \(\quad\) \(\text{1 s, 512 MB}\)

题解

倘若可以被重排成值域上连续的一段,那么处于哪一段上也就是也可以确定的,令区间最大最小值分别为 \(Max\)\(Min\),那么在值域上连续一定是 \([Min,Max]\),问题转换为判断区间是否能和 \([Min,Max]\) 重合。

从数颜色的角度是困难的,不妨换一个思路,类似哈希的思想,先预处理值域上的前缀平方和,再用线段树维护区间平方和,最后判断值是否相同即可,可以选择取模或者 unsigned long long 自然溢出。


还有一种方法是维护前继相同的值,询问时先判断 \([Min,Max]\) 的长度是否和区间长度相同,后判断区间内元素最大前继是否落在区间内即可。

时间复杂度均为 \(\mathcal{O}(n\log n)\)

哈希 + 自然溢出实现:

#include <bits/stdc++.h>
using namespace std;

const int N = 5e5 + 5,NN = 2.5e7 + 5;

int n,q,a[N],Vmax = INT_MIN;

#define ull unsigned int long long

struct XDT{
    int l,r,mi,ma; ull sum;
}t[N << 2];

#define ls p << 1
#define rs p << 1 | 1

void pushup(int p){
    t[p].mi = min(t[ls].mi,t[rs].mi);
    t[p].ma = max(t[ls].ma,t[rs].ma);
    t[p].sum = t[ls].sum + t[rs].sum;
}

void build(int p,int l,int r){
    t[p].l = l, t[p].r = r;
    if (l == r){
        t[p].mi = t[p].ma = a[l];
        t[p].sum = (ull)a[l] * a[l];
        return ;
    }
    int mid = (l + r) >> 1;
    build(ls,l,mid), build(rs,mid + 1,r);
    pushup(p);
}

void modify(int p,int x,int y){
    if (t[p].l == t[p].r){
        t[p].mi = t[p].ma = y;
        t[p].sum = y * y;
        return ;
    }
    int mid = (t[p].l + t[p].r) >> 1;
    if (x <= mid) modify(ls,x,y);
    else modify(rs,x,y);
    pushup(p);
}

ull querySUM(int p,int l,int r){
    if (l <= t[p].l && t[p].r <= r){
        return t[p].sum;
    }
    int mid = (t[p].l + t[p].r) >> 1; ull val = 0;
    if (l <= mid) val += querySUM(ls,l,r);
    if (r > mid) val += querySUM(rs,l,r);
    return val;
}

int queryMAX(int p,int l,int r){
    if (l <= t[p].l && t[p].r <= r){
        return t[p].ma;
    }
    int mid = (t[p].l + t[p].r) >> 1, val = INT_MIN;
    if (l <= mid) val = max(val,queryMAX(ls,l,r));
    if (r > mid) val = max(val,queryMAX(rs,l,r));
    return val;
}

int queryMIN(int p,int l,int r){
    if (l <= t[p].l && t[p].r <= r){
        return t[p].mi;
    }
    int mid = (t[p].l + t[p].r) >> 1, val = INT_MAX;
    if (l <= mid) val = min(val,queryMIN(ls,l,r));
    if (r > mid) val = min(val,queryMIN(rs,l,r));
    return val;
}

ull s[NN];

int read(){
    int x = 0; char ch = getchar();
    while (ch < '0' || ch > '9'){
        ch = getchar();
    }
    while ('0' <= ch && ch <= '9'){
        x = (x << 1) + (x << 3) + (ch ^ 48);
        ch = getchar();
    }
    return x;
}

int main(){
    n = read(), q = read();
    for (int i = 1;i <= n;i++) a[i] = read(), Vmax = max(Vmax,a[i]);
    for (int i = 1;i <= Vmax;i++) s[i] = s[i - 1] + (ull)i * i;
    build(1,1,n);
    while (q--){
        int o = read(),l = read(),r = read();
        if (o == 1)
            modify(1,l,r);
        else{
            if (querySUM(1,l,r) == s[queryMAX(1,l,r)] - s[queryMIN(1,l,r) - 1])
                puts("damushen");
            else 
                puts("yuanxing");
        }
    }
    return 0;
}
posted @ 2024-07-15 10:29  _yiwei  阅读(9)  评论(0编辑  收藏  举报