区间修改&&单点查询(树状数组)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<list> #include<map> #include<queue> #include<set> #include<cmath> typedef long long ll; using namespace std; inline ll read(){ ll sum=0; int x=1 ; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') x=0; ch=getchar(); } while(ch>='0'&&ch<='9') sum=(sum<<1)+(sum<<3)+(ch^48),ch=getchar(); return x?sum:-sum; } inline void write(ll x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } const int M=1e6+5; int n; ll bit[M],a[M]; void update(int l,ll x){ // cout<<"!"<<endl; while(l<=n) bit[l]+=x,l+=l&(-l); } ll query(int x){ ll ans=0; while(x) ans+=bit[x],x-=x&(-x); return ans; } int main(){ n=read(); int m=read(); for(int i=1;i<=n;i++){ a[i]=read(); update(i,a[i]-a[i-1]); } // bit[i]=read(); //cout<<n<<endl; /*for(int i=1;i<=n;i++) cout<<bit[i]<<" "; cout<<endl;*/ while(m--){ int op=read(); if(op==1){ int l=read(),r=read(),x=read(); update(l,x); update(r+1,-x); } else{ int x=read(); write(query(x)); putchar(' '); } } return 0; }
单点修改&&区间查询(树状数组)
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #include<vector> #include<list> #include<map> #include<queue> #include<set> #include<cmath> typedef long long ll; using namespace std; inline ll read(){ ll sum=0; int x=1 ; char ch=getchar(); while(ch<'0'||ch>'9'){ if(ch=='-') x=0; ch=getchar(); } while(ch>='0'&&ch<='9') sum=(sum<<1)+(sum<<3)+(ch^48),ch=getchar(); return x?sum:-sum; } inline void write(ll x){ if(x<0) putchar('-'),x=-x; if(x>9) write(x/10); putchar(x%10+'0'); } const int M=1e6+5; int n; ll bit[M]; void update(int x,ll a){ // cout<<"!"<<endl; while(x<=n) bit[x]+=a,x+=x&(-x); } ll query(int u,int v){ ll ans1=0,ans2=0; while(v) ans1+=bit[v],v-=v&(-v); u--; while(u) ans2+=bit[u],u-=u&(-u); // cout<<ans1<<"!!"<<ans2<<endl; return ans1-ans2; } int main(){ n=read(); int m=read(); for(int i=1;i<=n;i++){ int z=read(); update(i,z); } // bit[i]=read(); //cout<<n<<endl; while(m--){ int op=read(),x=read(),y=read(); if(op==1) update(x,y); else{ write(query(x,y)); putchar(' '); } } return 0; }
线段树板
#include<bits/stdc++.h> using namespace std; #define ll long long #define ls rt<<1,l,m #define rs rt<<1|1,m+1,r #define pb push_back const int INF=0x3f3f3f3f; const int N=1e6+5; int tree[4*N]; int lazy[4*N]; //将子节点值更新到父亲节点 /*对于区间求和而言*/ void push_up(int rt) { tree[rt]=tree[rt<<1]+tree[rt<<1|1]; } //节点懒惰标记下推 /*对于区间求和而言*/ void push_down(int rt,int len) { tree[rt<<1]+=lazy[rt]*(len-(len>>1)); lazy[rt<<1]+=lazy[rt]; tree[rt<<1|1]+=lazy[rt]*(len>>1); lazy[rt<<1|1]+=lazy[rt]; lazy[rt]=0; } //建树 void build(int rt,int l,int r) { if(l==r) { scanf("%d",&tree[rt]);//最好用scanf,防止超时 return ; } int m=(l+r)>>1; build(ls); build(rs); push_up(rt); } //单节点更新 void update(int p,int delta,int rt,int l,int r) { if(l==r) { tree[rt]+=delta; return ; } int m=(l+r)>>1; if(p<=m)update(p,delta,ls); else update(p,delta,rs); push_up(rt); } //区间更新 void Update(int L,int R,int delta,int rt,int l,int r) { if(L<=l&&r<=R) { tree[rt]+=(r-l+1)*delta; lazy[rt]+=delta; return ; } if(lazy[rt])push_down(rt,r-l+1); int m=(l+r)>>1; if(L<=m)Update(L,R,delta,ls); if(R>m)Update(L,R,delta,rs); push_up(rt); } //区间查询 /*对于区间求和而言*/ int query(int L,int R,int rt,int l,int r) { if(L<=l&&r<=R)return tree[rt]; if(lazy[rt])push_down(rt,r-l+1); int m=(l+r)>>1,res=0; if(L<=m)res+=query(L,R,ls); if(R>m)res+=query(L,R,rs); return res; }
经典求区间最大前缀和
题:https://codeforces.com/contest/1263/problem/E
#include<bits/stdc++.h> using namespace std; typedef long long ll; #define lson root<<1,l,midd #define rson root<<1|1,midd+1,r #define pb push_back const int inf=0x3f3f3f3f; const ll INF=1e18; const int M=1e6+6; int tree[M<<2]; int lzmi[M<<2];///最小前缀和 int lzma[M<<2];///最大前缀和 char s[M]; void up(int root){ tree[root]=tree[root<<1]+tree[root<<1|1]; lzma[root]=max(lzma[root<<1],tree[root<<1]+lzma[root<<1|1]);///右区间来选前缀时要考虑到左区间带进来的贡献 lzmi[root]=min(lzmi[root<<1],tree[root<<1]+lzmi[root<<1|1]); } void update(int p,int v,int root,int l,int r){ if(l==r){ tree[root]=lzmi[root]=lzma[root]=v; return ; } int midd=(l+r)>>1; if(p<=midd) update(p,v,lson); else update(p,v,rson); up(root); } int main(){ int n; scanf("%d%s",&n,s); int nowpos=1; for(int i=0;i<n;i++){ if(s[i]=='L') nowpos=max(1,nowpos-1); else if(s[i]=='R') nowpos++; else if(s[i]=='(') update(nowpos,1,1,1,n); else if(s[i]==')') update(nowpos, -1,1,1,n); else update(nowpos,0,1,1,n); ///若全区间和不为0,则证明左括号数和右括号数不等 ///若全区间最小前缀和不为0,则证明有一个右括号没有被左括号对应, if(lzmi[1]<0||tree[1]!=0) printf("-1 "); else printf("%d ",lzma[1]); } return 0; }
二维线段树板子
区间查询:
int query_y(int l,int r,int rt,int d) { if(L2<=l&&R2>=r) return sum[d][rt]; int mid = (l+r)>>1,ans = 0; if(L2<=mid) ans += query_y(lson,d); if(R2>mid) ans += query_y(rson,d); return ans; } int query_x(int l,int r,int rt) { if(L1<=l&&R1>=r) return query_y(1,m,1,rt); int mid = (l+r)>>1,ans = 0; if(L1<=mid) ans += query_x(lson); if(R1>mid) ans += query_x(rson); return ans; }
单点更新加1:
void update_y(int l,int r,int rt,int d) { sum[d][rt]++;//将所有包含(L1,R1)的矩阵+1即可 if(l==r) return; int mid = (l+r)>>1; if(R1<=mid) update_y(lson,d); else update_y(rson,d); } void update_x(int l,int r,int rt) { update_y(1,m,1,rt); if(l==r) return ; int mid = (l+r)>>1; if(L1<=mid) update_x(lson); else update_x(rson); update_y(1,m,1,rt); }