4 条题解
-
2
阎帝小代码
#include<bits/stdc++.h> #define int long long #define lc(p) (p<<1) #define rc(p) (p<<1|1) using namespace std; const int N=6e5+10;//不清楚为什么要开6e5,我开5e5就RE struct node{int l,r,sum;}t[N<<2]; int a[N],n,q; void pu(int p){t[p].sum=t[lc(p)].sum+t[rc(p)].sum;} void build(int id,int l,int r) { t[id]={l,r,0}; if(l==r){t[id].sum=a[l];return ;} int m=l+r>>1; build(lc(id),l,m);build(rc(id),m+1,r); pu(id); } void change(int p,int x,int y) { if(x<t[p].l||x>t[p].r)return ; t[p].sum+=y; change(lc(p),x,y);change(rc(p),x,y); } int query(int p,int l,int r) { if(r<t[p].l||t[p].r<l)return 0; if(l<=t[p].l&&t[p].r<=r)return t[p].sum; return query(lc(p),l,r)+query(rc(p), l,r); } signed main() { scanf("%lld%lld",&n,&q); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); build(1,1,n); while(q--) { int op,x,y;scanf("%lld%lld%lld",&op,&x,&y);x++; if(op==0) { change(1,x,y); } else { printf(" %lld\n",query(1,x,y)); } } return 0; } -
1
点修区查,这不树状数组板子吗。
注意下标需要整体加 ,树状数组本身不支持下标 作为有效操作节点。
提交记录:626ms,8 MiB这不比线段树香吗
#include<bits/stdc++.h> using namespace std; #define int ll #define In inline #define ll long long #define rep(i,x,y) for(int i=x;i<=y;++i) #define per(i,x,y) for(int i=x;i>=y;--i) In void ios_off(){ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);} const int N=5e5+10; int n,q,c[N]; int lowbit(int x){return x&-x;} void add(int x,int k){for(;x<=n;x+=lowbit(x))c[x]+=k;} int query(int x) { int res=0; for(;x;x-=lowbit(x))res+=c[x]; return res; } signed main() { ios_off(); cin>>n>>q; rep(i,1,n) { int x;cin>>x; add(i,x); } rep(i,1,q) { int op;cin>>op; if(op==0) { int p,x;cin>>p>>x; add(p+1,x); } else { int l,r;cin>>l>>r; cout<<query(r)-query(l)<<'\n'; } } return 0; } -
1
你是说不想在以后出现函数名重复的情况?
那就试试结构体吧!!!
线段树:
#include<bits/stdc++.h> using namespace std; #define int long long const int N=5e5+10; int a[N]; #define lc(p) (p<<1) #define rc(p) (p<<1|1) struct node{int l,r,s;}; struct SMT{ node tr[N<<2]; void pushup(int p){tr[p].s=tr[lc(p)].s+tr[rc(p)].s;} void bt(int p,int l,int r) { tr[p]={l,r,0}; if(l==r){tr[p].s=a[l];return;} int mid=(l+r)>>1; bt(lc(p),l,mid);bt(rc(p),mid+1,r); pushup(p); } void change(int p,int x,int k) { if(tr[p].l>x||tr[p].r<x)return ; if(tr[p].l==tr[p].r) { tr[p].s+=k; return; } change(lc(p),x,k);change(rc(p),x,k); pushup(p); } int query(int p,int l,int r) { if(tr[p].l>r||tr[p].r<l)return 0; if(l<=tr[p].l&&tr[p].r<=r)return tr[p].s; return query(lc(p),l,r)+query(rc(p),l,r); } }tr; #undef lc(p) #undef rc(p) signed main() { int n,q;cin>>n>>q; for(int i=1;i<=n;i++)cin>>a[i]; tr.bt(1,1,n); while(q--) { int op,x,y;cin>>op>>x>>y; if(op==0)tr.change(1,x+1,y); else cout<<tr.query(1,x+1,y)<<'\n'; } return 0; }树状数组:
#include<bits/stdc++.h> using namespace std; #define int long long const int N=5e5+10; struct BIT{ int c[N],n; void add(int x,int k){for(;x<=n;x+=x&-x)c[x]+=k;} int ask(int x){int ans=0;for(;x;x-=x&-x)ans+=c[x];return ans;} }tr; int a[N]; signed main() { int n,q;cin>>n>>q;tr.n=n; for(int i=1;i<=n;i++)cin>>a[i],tr.add(i,a[i]); while(q--) { int op,x,y;cin>>op>>x>>y; if(op==0)tr.add(x+1,y); else cout<<(tr.ask(y)-tr.ask(x))<<'\n'; } return 0; } -
1
#include<bits/stdc++.h> using namespace std; #define lc(p) (p << 1) /*i的左孩子编号为i*2*/ #define rc(p) (p << 1 | 1) /*i的右孩子编号为i*2+1*/ const int N = 6e5 + 10; #define int long long int a[N];/*记录数组初值*/ struct node {int l/*左区间*/, r/*右区间*/, v/*区间最小值*/;}tr[N << 2]/*开四倍, 防炸*/; void pushup(int p){tr[p].v = tr[lc(p)].v + tr[rc(p)].v;}/*更新节点权值*/ void build(int p, int l, int r)/*节点p管理区间[l,r]构造线段树*/ { tr[p] = {l, r, 0};/*赋值节点p*/ if (l == r)/*如果只管理一个点*/ {tr[p].v = a[l];/*直接赋值权值*/ return;/*已经到最低层了*/ } int mid = (l + r) >> 1; build(lc(p), l, mid);/*左孩子管理p管理范围的左半边*/ build(rc(p), mid + 1, r);/*右孩子管理剩下右半边*/ pushup(p);/*递归回来时更新p的区间和*/ } int query(int p, int l, int r)/*查询区间[l,r]的区间和*/ { if (r < tr[p].l or tr[p].r < l)/*如果p管理区间与[l,r]无关*/ return 0;/*对答案贡献为0*/ if (l <= tr[p].l and tr[p].r <= r)/*p区间在区间[l,r]内*/ return tr[p].v;/*不会贡献区间以外的答案, 直接返回p的权值*/ /*如果p包括了查询区间以外的值, 就将区间细分到左右儿子再统计*/ return query(lc(p), l, r) + query(rc(p), l, r); } void change(int p, int x, int y)/*将a[x]的值加上y*/ { if (x < tr[p].l or tr[p].r < x)/*如果x不在p管理区间内*/ return; tr[p].v += y;/*如果x在p管理区间内, p的区间和加y*/ change(lc(p), x, y); change(rc(p), x, y);/*递归修改左右孩子的区间和*/ } signed main() { int n, q; cin >> n >> q; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); while (q--) { int op, x, y; cin >> op >> x >> y; x ++; if (op == 0) change(1, x, y); else cout << query(1, x, y) << '\n'; } return 0; }#include<bits/stdc++.h> using namespace std; #define int long long #define lc(p) tr[p].ls #define rc(p) tr[p].rs const int N = 5e5 + 10; struct node{int val, ls, rs;}tr[N << 2]; int trlen = 1, rt, a[N]; void pushup(int p){tr[p].val = tr[lc(p)].val + tr[rc(p)].val;} void build(int p, int l, int r) { tr[p] = {0, 0, 0}; if (l == r) {tr[p].val = a[l]; return;} int mid = (l + r) >> 1; lc(p) = ++trlen; build(lc(p), l, mid); rc(p) = ++trlen; build (rc(p), mid + 1, r); pushup(p); } void change(int p, int l, int r, int k, int x) { if (l == r) {tr[p].val += x; return; } int mid = (l + r) >> 1; if (k <= mid) change(lc(p), l, mid, k, x); else change(rc(p), mid + 1, r, k, x); pushup(p); } int query(int p, int l, int r, int x, int y) { if (y < l or r < x) return 0; if (x <= l and r <= y) return tr[p].val; int mid = (l + r) >> 1; return query(lc(p), l, mid, x, y) + query(rc(p), mid + 1, r, x, y); } signed main() { int n, q; cin >> n >> q; for (int i = 1; i <= n; i++) cin >> a[i]; build(1, 1, n); while (q--) { int op, x, y; cin >> op >> x >> y; if (op == 0) change(1, 1, n, x + 1, y); else if (op == 1) cout << query(1, 1, n, x + 1, y) << endl; } return 0; }
- 1
信息
- ID
- 8126
- 时间
- 1000ms
- 内存
- 1024MiB
- 难度
- 6
- 标签
- 递交数
- 55
- 已通过
- 16
- 上传者