線段樹綜合

 單點操作和區間查詢

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
const int maxn = 1e5+5;
int sum[maxn<<2];
void pushup(int rt)
{
	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt)
{
	if(l == r)
	{
		scanf("%d",&sum[rt]);
		return ;
	}
	int mid = (l+r)>>1;
	build(l,mid,rt<<1);
	build(mid+1,r,rt<<1|1);
	pushup(rt);
}
void update(int p,int v,int l,int r,int rt)
{
	if (l == r)
	{
		sum[rt] += v;//+-*/都行 
		return ;
	}
	ll m = (l+r) >> 1;
	if (p <= m)
		update(p, v, l, m, rt << 1);
	else
		update(p, v, m+1, r, rt << 1 | 1);
	pushup(rt);
}
int query(int l,int r,int L,int R,int rt)
{
	if(L >= l && R <= r)
	{
		return sum[rt];
	}
	ll mid = (R+L)>>1;
	int ans = 0;
	if(l<=mid)
	{
		ans += query(l,r,L,mid,rt<<1);
	}
	if(r>mid){
		ans += query(l,r,mid+1,R,rt<<1|1);
	}
	pushup(rt);	
	return ans;
}//單點建樹及區間查詢 
int main()
{
	int t;int cnt  = 1;
	scanf("%d",&t);
	while(t--)
	{
		printf("Case %d:\n",cnt);
		cnt++;
		int n;
		scanf("%d",&n);
		build(1,n,1);
		string s;
		while(1)
		{
			cin>>s;
			int h,rr;
			if(s == "Query")
			{
				scanf("%d%d",&h,&rr);
				printf("%d\n",query(h,rr,1,n,1));
			}
			else if(s == "Add")
			{
				scanf("%d%d",&h,&rr);
				update(h,rr,1,n,1);
			}
			else if(s == "Sub")
			{
				scanf("%d%d",&h,&rr);
				update(h,-rr,1,n,1);
			}
			else
			{
				break;
			}
		}
	}
	return 0;
}//適合與單點最簡點那種

簡單的區間更新和查詢總數

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define ll long long
#define rson rt<<1|1
#define lson rt<<1
ll _sum,_min,_max;
const ll MAXN = 1e5+5;
ll st[MAXN<<2],stmin[MAXN<<2],stvis[MAXN<<2],stmax[MAXN<<2];
ll a[MAXN];
void push_up(ll rt)
{
    stmax[rt]=max(stmax[lson],stmax[rson]);
    stmin[rt]=min(stmin[lson],stmin[rson]);
    st[rt]=st[lson]+st[rson];//修改位置
}
void push_down(ll rt,ll sec)          //rt標記節點 sec區間
{
    stvis[lson]+=stvis[rt];
    st[lson]+=stvis[rt]*(sec-(sec>>1));
    stmin[lson]+=stvis[rt];
    stmax[lson]+=stvis[rt];
 
    stvis[rson]+=stvis[rt];
    st[rson]+=stvis[rt]*(sec>>1);
    stmin[rson]+=stvis[rt];
    stmax[rson]+=stvis[rt];
    stvis[rt]=0;
}
void build(ll l,ll r,ll rt)
{
    stvis[rt]=0;
    if(l==r)
    {
        stmax[rt]=stmin[rt]=st[rt]=a[l];
        return;
    }
    ll mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    push_up(rt);
}//建樹 
void mod_update(int L,int R,int mod,int l,int r,int rt)//區間mod
{
    if(stmax[rt]<mod)
        return;
    if(l==r)
    {
        st[rt]%=mod;
        stmax[rt]=st[rt];
        return;
    }
    int mid=(l+r)>>1;
    if(L<=mid)
        mod_update(L,R,mod,l,mid,lson);
    if(mid<R)
        mod_update(L,R,mod,mid+1,r,rson);
    push_up(rt);
}
void update(ll L,ll R,ll v,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
    {
        stvis[rt]+=v;
        st[rt]+=v*(r-l+1);
        stmin[rt]+=v;
        stmax[rt]+=v;
        return;
    }
    if(stvis[rt])
        push_down(rt,r-l+1);
    ll mid=(l+r)>>1;
    if(L<=mid)
        update(L,R,v,l,mid,lson);
    if(mid<R)
        update(L,R,v,mid+1,r,rson);
    push_up(rt);
}//更新區間的值
ll query(ll L,ll R,ll l,ll r,ll rt)
{
    if(L<=l&&r<=R)
        return st[rt];
    if(stvis[rt])
        push_down(rt,r-l+1);
    ll mid=(l+r)>>1;
    ll sum=0;
    if(L<=mid)
        sum+=query(L,R,l,mid,lson);//修改位置
    if(mid<R)
        sum+=query(L,R,mid+1,r,rson);//修改位置
    return sum;
}//區間查詢總數 
int main() {
  ll n, m;
	scanf("%lld%lld", &n, &m) ; 
  
  	for(ll i = 1;i <= n;++i)
  	{
  		scanf("%lld",&a[i]);
	}
	build(1,n,1);
    while(m--) 
	{
    	char tt;
    	cin>>tt;
    	ll v1,v2;ll v3;
	    if(tt == 'C') 
		{
	    	scanf("%lld%lld%lld", &v1,&v2,&v3);
			update(v1,v2,v3,1,n,1);
	    }
	   else {
	   	scanf("%lld%lld",&v1,&v2);      
        printf("%lld\n", query(v1,v2,1,n,1));
      }
    }
  return 0;
}

求區間最值如果單單是這樣可以用rmq

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define inf 0x3f3f3f3f
#define ll long long
#define rson rt<<1|1
#define lson rt<<1
const ll MAXN = 1e5+5;
using namespace std;
ll st[MAXN<<2],stmin[MAXN<<2],stvis[MAXN<<2],stmax[MAXN<<2];
ll a[MAXN];
void push_up(int rt)
{
    stmax[rt]=max(stmax[lson],stmax[rson]);
    stmin[rt]=min(stmin[lson],stmin[rson]);
    st[rt]=st[lson]+st[rson];//修改位置
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        stmax[rt]=stmin[rt]=st[rt]=a[l];
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,lson);
    build(mid+1,r,rson);
    push_up(rt);
}
ll query1(int L,int R,int l,int r,int rt)
{
    if(L <= l && r <= R)
        return stmax[rt];
    int mid = (l+r)>>1;ll sum = -inf;
    if(L <= mid)
        sum = max(sum,query1(L,R,l,mid,lson));//修改位置
    if(mid < R)
        sum = max(sum,query1(L,R,mid+1,r,rson));//修改位置
    return sum;
}//查詢區間最大 
ll query2(int L,int R,int l,int r,int rt)
{
    if(L <= l &&r<=R)
        return stmin[rt];
    int mid=(l+r)>>1;ll sum = inf;
    if(L <= mid)
        sum = min(sum,query2(L,R,l,mid,lson));//修改位置
    if(mid < R)
        sum = min(sum,query2(L,R,mid+1,r,rson));//修改位置
    return sum;
}//查詢區間最小 
int main()
{
	int n,q;
	scanf("%d%d",&n,&q);
	for(int i = 1;i <= n;++i)
	{
		scanf("%d",&a[i]);
	}
	int l,r;
	build(1,n,1);
	for(int i = 0;i < q;++i)
	{
		scanf("%d%d",&l,&r);
		int g = query1(l,r,1,n,1)-query2(l,r,1,n,1);
		printf("%d\n",g);
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章