1. 程式人生 > >線段樹(單點修改,區間查詢)

線段樹(單點修改,區間查詢)

/*
 * 線段樹模板
 * 單點修改,區間查詢
 */
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long LL;
const int MAXN=1e5+5;//
const int INF=0x3f3f3f3f;//根據是否超long long修改
int a[MAXN];

//線段樹節點結構體
struct Node{
    int left,right;//左右邊界
    int mi,ma;//最小值 最大值
    LL sum;//和
}tree[MAXN*4];//空間開四倍

//向上更新
void PushUp(int rt){ tree[rt].mi=min(tree[rt<<1].mi,tree[rt<<1|1].mi); tree[rt].ma=max(tree[rt<<1].ma,tree[rt<<1|1].ma); tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } //建立函式 void Build(int rt,int L,int R){ tree[rt].left=L;tree[rt].right=R; if
(L==R) {tree[rt].sum=tree[rt].mi=tree[rt].ma=a[L]; return;} int mid=(tree[rt].left+tree[rt].right)>>1; Build(rt<<1,L,mid);//只有Build時LR才會變 Build(rt<<1|1,mid+1,R); PushUp(rt); } LL QuerySum(int rt,int L,int R){ if(L<=tree[rt].left&&tree[rt].right<=R) return
tree[rt].sum;//貢獻為tree[rt].sum int mid=(tree[rt].left+tree[rt].right)>>1; LL res=0; if(L<=mid) res+=QuerySum(rt<<1,L,R); if(R>mid) res+=QuerySum(rt<<1|1,L,R); return res; } int QueryMin(int rt,int L,int R){ if(L<=tree[rt].left&&tree[rt].right<=R) return tree[rt].mi; int mid=(tree[rt].left+tree[rt].right)>>1; int res=INF; if(L<=mid) res=min(res,QueryMin(rt<<1,L,R)); if(R>mid) res=min(res,QueryMin(rt<<1|1,L,R)); return res; } int QueryMax(int rt,int L,int R){ if(L<=tree[rt].left&&tree[rt].right<=R) return tree[rt].ma;//完全包含才產生貢獻 int mid=(tree[rt].left+tree[rt].right)>>1; int res=-INF; if(L<=mid) res=max(res,QueryMax(rt<<1,L,R)); if(R>mid) res=max(res,QueryMax(rt<<1|1,L,R)); return res; } void Update(int rt,int pos,int x){//把pos位的值改為x if(tree[rt].left==tree[rt].right) { tree[rt].sum=tree[rt].mi=tree[rt].ma=x; return; } int mid=(tree[rt].left+tree[rt].right)>>1; if(pos<=mid) Update(rt<<1,pos,x); else Update(rt<<1|1,pos,x); PushUp(rt); } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF){ for(int i=1;i<=n;i++) scanf("%d",&a[i]); Build(1,1,n);//建立線段樹 int op,x,y; for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&x,&y); if(op==1){//詢問[x,y]的和 printf("%lld\n",QuerySum(1,x,y)); }else if(op==2){//詢問[x,y]的最大值 printf("%d\n",QueryMax(1,x,y)); }else if(op==3){//詢問[x,y]的最小值 printf("%d\n",QueryMin(1,x,y)); }else{//修改第x位的值為y Update(1,x,y); } } } return 0; } /* 6 4 1 2 3 4 5 6 4 3 8 1 1 6 2 1 6 3 1 6 */
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson (rt<<1)
#define rson (rt<<1|1)
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long LL;
const int MAXN=2e5+5;
int val[MAXN];

struct node
{
    int ma,left,right;
}tree[MAXN*4];

void pushup(int rt)
{
    tree[rt].ma=max(tree[lson].ma,tree[rson].ma);
}

void build(int rt,int left,int right)
{
    tree[rt].left=left;
    tree[rt].right=right;
    if(left==right) {tree[rt].ma=val[left];return;}
    int mid=(left+right)>>1;
    build(lson,left,mid);
    build(rson,mid+1,right);
    pushup(rt);
}

int query(int rt,int left,int right)
{
    if(left<=tree[rt].left&&tree[rt].right<=right) return tree[rt].ma;
    int m=(tree[rt].left+tree[rt].right)>>1;
    int res=0;
    if(left<=m) res=max(res,query(lson,left,right));
    if(right>m) res=max(res,query(rson,left,right));
    return res;
}

void update(int rt,int pos,int val)
{
    if(tree[rt].left==tree[rt].right) {tree[rt].ma=val;return;}
    int m=(tree[rt].left+tree[rt].right)>>1;
    if(pos<=m) update(lson,pos,val);
    else update(rson,pos,val);
    pushup(rt);
}

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        for(int i=1;i<=n;++i)
            scanf("%d",&val[i]);
        build(1,1,n);
        for(int i=1;i<=m;++i)
        {
            getchar();
            char op;int x,y;
            scanf("%c",&op);
            scanf("%d%d",&x,&y);
            if(op=='Q')
            {
                printf("%d\n",query(1,x,y));
            }else
            {
                update(1,x,y);
            }
        }
    }
    return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define mem(a,b) memset(a,b,sizeof(a))
#define lson rt<<1
#define rson rt<<1|1
using namespace std;
typedef long long LL;
const int INF=0x3f3f3f3f;
const double eps=1e-10;
const int MAXN=1e5+5;
const int MOD=1e9+7;
int a[MAXN];
int minv[MAXN*4];

void build(int l,int r,int rt)
{
    if(l==r) {minv[rt]=a[l];return;}
    int m=l+(r-l)/2;
    build(l,m,rt*2);
    build(m+1,r,rt*2+1);
    minv[rt]=min(minv[rt*2],minv[rt*2+1]);
}

int query(int o,int L,int R,int ql,int qr)
{
    int M=L+(R-L)/2,ans=INF;
    if(ql<=L&&R<=qr) return minv[o];//當前結點完全包含在查詢區間內
    if(ql<=M) ans=min(ans,query(o*2,L,M,ql,qr));//往左走
    if(M<qr) ans=min(ans,query(o*2+1,M+1,R,ql,qr));//往右走
    return ans;
}

void update(int o,int L,int R,int p,int v)//修改A[p]=v
{
    int M=L+(R-L)/2;
    if(L==R) minv[o]=v;//葉結點,直接更新minv
    else
    {
        if(p<=M) update(o*2,L,M,p,v);
        else update(o*2+1,M+1,R,p,v);
        minv[o]=min(minv[o*2],minv[o*2+1]);
    }
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;scanf("%d",&n);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&a[i]);
        }
        build(1,n,1);
        int q;
        scanf("%d",&q);
        int op,x,y;
        for(int i=1;i<=q;++i)
        {
            cin>>op>>x>>y;
            if(op==1)
            {
                update(1,1,n,x,y);
            }else if(op==2)
            {
                cout<<query(1,1,n,x,y)<<endl;
            }
        }
    }
    return 0;
}
/*
10
10
1 2 3 4 5 6 7 8 9 10
100
1 1 2
*/