3 条题解

  • 0
    @ 2023-9-5 17:53:10

    暑假的救赎系列day3 注意注意! k<<1 + 1 是cuowud 应该写成 (k << 1) + 1 其他没什么

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 2e5 + 10;
    int sum[4*N],a[N],n,m;
    void check()
    {
    	for(int i=1; i <= 10 ;i++)
    	{
    		cout << sum[i] << " ";
    	}
    	cout << endl;
    }
    void build(int k,int l,int r)
    {
    	if(l == r)
    	{
    		sum[k] = a[l];
    		return;
    	}
    	int mid = (l+r )/ 2;
    	build(k *2 , l,mid);
    	build(k *2 + 1,mid+1,r);
    	sum[k] = sum[k*2] + sum[k * 2 + 1];
    }
    int sm(int k,int l,int r,int s,int t)
    {
    	if( s <= l && r <= t)
    	{
    		return sum[k];
    	}
    	int mid = (l + r) /2 ;
    	int ans = 0;
    	if(mid >= s) ans += sm(k*2,l,mid,s,t);
    	if(mid + 1 <= t) ans += sm(k*2+1,mid+1,r,s,t);
    	return ans; 
    }
    void change(int k,int l,int r,int id,int x)
    {
    	if(l == r)
    	{
    		sum[k] = x;
    		return;
    	}
    	int mid = (l + r) /2;
    	if(mid >= id) change(k*2,l,mid,id,x);
    	else change(k*2+ 1 ,mid + 1,r,id,x);
    	sum[k] = sum[k*2] + sum[k *2 + 1];
    }
    int main()
    {
    	cin >> n>> m;
    	for(int i=1; i <= n ;i++)
    	{
    		cin >> a[i];
    	}
    	build(1,1,n);
    	for(int i=1; i <= m ;i++)
    	{
    		int op,l,r,x,y;
    		cin >> op;
    		if(op == 1) 
    		{
    			cin >> x >> y;
    			change(1,1,n,x,y);
    		}
    		if(op == 2)
    		{
    			cin >> l >> r;
    			cout << sm(1,1,n,l,r) << endl;
    		}
    	}
    	return 0;
    }
    
    • 0
      @ 2023-6-1 20:00:48

      基础线段树习题

      #include <bits/stdc++.h>
      #define ll long long
      using namespace std;
      const int N = 200005;
      int n,m,k,s,t,opt,x,y;
      int a[N];//线段树维护的原数组
      struct Segment_Tree{
      	#define mid (l+r>>1)
      	int sum[N<<2];//存储线段树的区间和,空间记得开到4倍 
      	void pushup(int p){//节点信息的向上合并 
      		sum[p]=sum[p<<1]+sum[p<<1|1];
      	}
      	void build(int p,int l,int r){
      		if (l==r) {//叶子节点,对应原数列的初始区间 
      			sum[p]=a[l];
      			return;
      		}
      		build(p<<1,l,mid);//建左子树 
      		build(p<<1|1,mid+1,r);//建右子树 
      		pushup(p);//把子树信息合并到当前点 
      	}
      	void change(int p,int l,int r,int s,int t){
      		//当前区间的节点编号为p,表示区间为[l,r]
      		//要修改的点为s,修改为t 
      		if (l==r) {//找到了要修改的单点,直接修改 
      			sum[p]=t;
      			return; 
      		}
      		if (s<=mid) change(p<<1,l,mid,s,t);
      		else change(p<<1|1,mid+1,r,s,t);
      		//根据要修改的位置在左右子树里找 
      		pushup(p); 
      		//由于信息被修改了,所以最后要沿途更新线段树节点的信息 
      	}
      	int query(int p,int l,int r,int s,int t){
      		//当前区间的节点编号为p,表示区间为[l,r]
      		//要查询区间[s,t]中每个数的和 
      		if (l>=s && r<=t) return sum[p];
      		//如果当前区间已经被答案包含,直接计入答案 
      		int ans=0;
      		if (s<=mid) ans=query(p<<1,l,mid,s,t);
      		if (t>mid) ans+=query(p<<1|1,mid+1,r,s,t);
      		//往左右子树分开找 
      		return ans; 
      	}
      }T; 
      int main()
      {
      	ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
      	cin>>n>>m;
      	for (int i=1;i<=n;++i) cin>>a[i];
      	T.build(1,1,n);
      	for (int i=1;i<=m;++i){
      		cin>>opt>>x>>y;
      		if (opt==1) T.change(1,1,n,x,y);
      		else cout<<T.query(1,1,n,x,y)<<"\n";
      	} 
      }
      
      • -1
        @ 2023-6-3 20:03:04
        #include <iostream>
        #define MAXN 500010
        
        using namespace std;
        
        int n , m , a[ MAXN ] , sum[ MAXN * 4 ];
        
        void build( int x , int l , int r )
        {
        //目前建立编号为x的节点,这个节点对应区间 [l,r]
        if( l == r )
        {
        sum[x] = a[l];
        return;
        }
        int mid = ( l + r ) / 2;
        build( 2 * x , l , mid );
        build( 2 * x + 1 , mid + 1 , r );
        sum[x] = sum[2 * x] + sum[2 * x + 1];
        }
        
        void modify( int x , int l , int r , int s , int t )
        {
        //目前递归到编号为x的节点,这个节点对应区间 [l,r],我要把a[s]的值修改为t
        if( l == r )
        {
        //递归到叶子了,编号为x的节点的sum对应a[s]的值
        sum[x] = t;
        return;
        }
        int mid = ( l + r ) / 2;
        if( s <= mid )
        {
        modify( 2 * x , l , mid , s , t );
        }
        else
        {
        modify( 2 * x + 1 , mid + 1 , r , s , t );
        }
        sum[x] = sum[2 * x] + sum[2 * x + 1];
        }
        
        int find( int x , int l , int r , int s , int t )
        {
        //目前递归到了编号为x的节点,这个节点对应区间 [l,r],我询问的区间是 [s,t]
        if( s <= l && r <= t )
        {
        return sum[x];
        }
        int ans = 0 , mid = ( l + r ) / 2;
        if( s <= mid )
        {
        ans += find( 2 * x , l , mid , s , t );
        }
        if( t >= mid + 1 )
        {
        ans += find( 2 * x + 1 , mid + 1 , r , s , t );
        }
        return ans;
        }
        
        int main()
        {
        cin >> n >> m;
        for( int i = 1 ; i <= n ; i++ )
        cin >> a[i];
        build( 1 , 1 , n );
        while( m-- )
        {
        int opt , s , t;
        cin >> opt >> s >> t;
        if( opt == 1 )
        {
        modify( 1 , 1 , n , s , t );
        }
        else
        {
        cout << find( 1 , 1 , n , s , t ) << endl;
        }
        }
        return 0;
        }
        
        
        
        • 1

        信息

        ID
        122
        时间
        1000ms
        内存
        256MiB
        难度
        4
        标签
        递交数
        100
        已通过
        50
        上传者