• 板子(含二维线段树)


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

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

      

  • 相关阅读:
    Java 老兵不死,Kotlin 蓄势待发
    程序员写代码时戴着耳机,在听什么?
    推荐 7 个提升前端编程效率的 VSCode 插件
    去掉烦人的 !=null
    透析!软件开发未来 10 年的 8 个趋势
    10月01日总结
    09月29日总结
    09月28日总结
    09月27日总结
    09月26日总结
  • 原文地址:https://www.cnblogs.com/starve/p/10820398.html
Copyright © 2020-2023  润新知