1 条题解
-
0
#include <bits/stdc++.h> using namespace std; #define lc(p) (p<<1) // 左孩子节点 #define rc(p) (p<<1|1) // 右孩子节点 typedef long long LL; const int N=1e5+5; // 数组大小 const LL inf=1e18; // 无穷大 struct trnode{int l,r;LL c,mx;}tr[4*N]; // 线段树节点:区间[ l,r ],和为c,最大值为mx LL a[N]; // 原始数组 // 向上更新:合并左右子节点的信息 void pushup(int p) { tr[p].c=tr[lc(p)].c+tr[rc(p)].c; tr[p].mx=max(tr[lc(p)].mx,tr[rc(p)].mx); } // 建树函数 void bt(int p, int l, int r) { tr[p]={l,r,0,inf}; // 初始化区间和为0,最大值为inf if(l==r){ // 叶子节点 tr[p].c=a[l]; // 区间和为原始值 tr[p].mx=a[l]; // 最大值为原始值 return ; } int m=(l+r)>>1; // 中间点 bt(lc(p),l,m); // 建左子树 bt(rc(p),m+1,r); // 建右子树 pushup(p); // 更新当前节点 } // 区间开方更新函数 void change(int p, int l, int r) { if(r<tr[p].l || tr[p].r<l)return ; // 不在区间内,直接返回 if(tr[p].mx<=1)return ; // 最大值<=1,无需开方(开方后不变) if(tr[p].l==tr[p].r){ // 叶子节点,开方 tr[p].c=sqrt(tr[p].c); tr[p].mx=sqrt(tr[p].mx); return; } change(lc(p),l,r); // 左子树更新 change(rc(p),l,r); // 右子树更新 pushup(p); // 更新当前节点 } // 区间查询函数 LL query(int p, int l, int r) { if(r<tr[p].l || tr[p].r<l)return 0; // 不在区间内,返回0 if(l<=tr[p].l&&tr[p].r<=r)return tr[p].c; // 完全包含,返回区间和 return query(lc(p),l,r)+query(rc(p),l,r); // 部分包含,递归查询左右子树 } int main() { int n;scanf("%d", &n); // 输入数组大小 for(int i=1;i<=n;i++)scanf("%lld", &a[i]); // 输入数组元素 bt(1,1,n); // 建立线段树 int m;scanf("%d", &m); // 输入操作次数 for(int i=1,op,l,r;i<=m;i++){ // 处理每次操作 scanf("%d%d%d", &op, &l, &r);if(l>r)swap(l,r); // 确保l<=r if(op==2)change(1,l,r); // 操作2:区间开方 else printf("%lld\n",query(1,l,r)); // 操作1:区间查询 } return 0; }
- 1
信息
- ID
- 4876
- 时间
- 1000ms
- 内存
- 512MiB
- 难度
- 8
- 标签
- 递交数
- 306
- 已通过
- 47
- 上传者