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; }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 单线程的Redis速度为什么快?
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 展开说说关于C#中ORM框架的用法!