区间修改&&单点查询(树状数组)
#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);
}