板子(含二维线段树)

区间修改&&单点查询(树状数组)

#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('\n');
		}
	}
	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('\n');
		}
	}
	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;
}
View Code

 二维线段树板子

区间查询:

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);

}

  题:https://ac.nowcoder.com/acm/contest/4120/I

#include<cstdio>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
#define lson root<<1,l,midd
#define rson root<<1|1,midd+1,r
const int M=3e3+3;
ll tr[M<<2][M<<2],a[M][M];
int n;
void updatey(int x,int y,ll c,int r1,int root,int l,int r){
    if(l==r){
        tr[r1][root]=max(tr[r1][root],c);
        return ;
    }
    int midd=(l+r)>>1;
    if(y<=midd) updatey(x,y,c,r1,lson);
    else updatey(x,y,c,r1,rson);
    tr[r1][root]=max(tr[r1][root<<1],tr[r1][root<<1|1]);
}
void updatex(int x,int y,ll c,int root,int l,int r){
    updatey(x,y,c,root,1,1,n);
    if(l==r)
        return ;
    int midd=(l+r)>>1;
    if(x<=midd)updatex(x,y,c,lson);
    else updatex(x,y,c,rson);
}
ll queryy(int x1,int y1,int x2,int y2,int r1,int root,int l,int r){
    if(y1<=l&&r<=y2){
        return tr[r1][root];
    }
    int midd=(l+r)>>1;
    ll res=0;
    if(y1<=midd)
        res=max(res,queryy(x1,y1,x2,y2,r1,lson));
    if(y2>midd)
        res=max(res,queryy(x1,y1,x2,y2,r1,rson));
    return res;
}
ll queryx(int x1,int y1,int x2,int y2,int root,int l,int r){
    if(x1<=l&&r<=x2){
        return queryy(x1,y1,x2,y2,root,1,1,n);
    }
    int midd=(l+r)>>1;
    ll res=0;
    if(x1<=midd)
        res=max(res,queryx(x1,y1,x2,y2,lson));
    if(x2>midd)
        res=max(res,queryx(x1,y1,x2,y2,rson));
    return res;
}
int main(){
    int m1,m2;
    scanf("%d%d%d",&n,&m1,&m2);
    for(int x1,x2,y1,y2,i=1;i<=m1;i++){
        ll w;
        scanf("%d%d%d%d%lld",&x1,&y1,&x2,&y2,&w);
        a[x1][y1]+=w;
        a[x1][y2+1]-=w;
        a[x2+1][y1]-=w;
        a[x2+1][y2+1]+=w;
    }
    for(int i=1;i<=n;i++)
        for(int j=1;j<=n;j++)a[i][j]+=a[i-1][j]+a[i][j-1]-a[i-1][j-1];
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++)
            updatex(i,j,a[i][j],1,1,n);
    }
    for(int x1,y1,x2,y2,i=1;i<=m2;i++){
        scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
        printf("%lld\n",queryx(x1,y1,x2,y2,1,1,n));
    }
    return 0;
}
View Code

 

posted @ 2019-05-06 16:27  starve_to_death  阅读(167)  评论(0编辑  收藏  举报