线段树

作者: _弓长_大人 | 来源:发表于2018-09-25 12:42 被阅读5次

专题

#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
#define N 50005
ll num[N];
ll sum[N<<2];
ll tree[N<<2];
char s[10];
int a,b,n;

void PushUp(int rt){

tree[rt]=tree[rt<<1]+tree[rt<<1|1];

}
void build(int l,int r,int rt){
if(l==r){
    tree[rt]=num[l];
    return;
}
int mid=(l+r)>>1;
build(l,mid,rt<<1);
build(mid+1,r,rt<<1|1);
PushUp(rt);
}

void update(int L,ll c,int l,int r,int rt){

if(l==r)
{

    tree[rt]+=c;
    return;
}
int mid=(l+r)>>1;
if(L<=mid){
    update(L,c,l,mid,rt<<1);
}else{
   update(L,c,mid+1,r,rt<<1|1);
}
PushUp(rt);
}

ll query(int L,int R,int l,int r,int rt){

ll ans=0;
if(L<=l&&R>=r){

return  tree[rt];

}
int mid=(r+l)>>1;
if(L<=mid){
    ans+=query(L,R,l,mid,rt<<1);
}
if(R>=mid+1){
    ans+=query(L,R,mid+1,r,rt<<1|1);
}

return ans;

}
int main()
{
    int T;
    scanf("%d",&T);

    for(int cas=1;cas<=T;cas++){
        printf("Case %d:\n",cas);
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%lld",&num[i]);
        }
         build(1,n,1);

         
        while(1){
            scanf("%s",&s);
            if(s[0]=='Q'){
                scanf("%d%d",&a,&b);
                printf("%lld\n",query(a,b,1,n,1));
            }else if(s[0]=='S'){ ll x; scanf("%d%lld",&a,&x);
                update(a,-x,1,n,1);
            }else if(s[0]=='A'){
                ll x; scanf("%d%lld",&a,&x);
                update(a,x,1,n,1);
            }else{
                break;
            }
        }
    }
    return 0;
}

B
线段树求逆序对


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define N 10005
ll a[N];
ll tree[N<<2];
int n;
void PushUp(int rt){
    tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void build(int l,int r,int rt){
if(l==r){
    tree[rt]=0;return;
}
int m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
PushUp(rt);
}
void updata(int L,int c,int l,int r,int rt){
if(l>r)
    return ;
if(l==r){
    tree[rt]++;
    return;
}
int m=(l+r)>>1;
if(L<=m) updata(L,c,l,m,rt<<1);
else  updata(L,c,m+1,r,rt<<1|1);

PushUp(rt);
}
ll query(int L,int R,int l,int r,int rt){

if(L>R)
    return 0;
if(L<=l&&R>=r){
    return tree[rt];
}
ll ans=0;
int m=(r+l)>>1;
if(L<=m) ans+=query(L,R,l,m,rt<<1);
if(R>m) ans+=query(L,R,m+1,r,rt<<1|1);
return ans;
}
ll ans[N];
ll mm[N];
int main()
{

    while(~scanf("%d",&n)){
        memset(tree,0,sizeof(tree));
        for(int i=1;i<=n;i++){
            scanf("%lld",&a[i]);
            a[i]++;
            a[i+n]=a[i];
        }
        int tn=n;
        n=2*n-1;
       for(int i=1;i<=tn;i++){
           updata(a[i],1,1,n,1);
           mm[i]=query(1,a[i]-1,1,n,1);
           ans[i]=ans[i-1]+i-1-mm[i];
        }

        ll temp=ans[tn];
        ll an=temp;
        for(int i=1;i<tn;i++){
            an=min(temp-(a[i]-1)+tn-a[i],an);
            temp=temp-(a[i]-1)+tn-a[i];
        }
         printf("%lld\n",an);
        }
    return 0;
}

C[]


#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long ll;
#define N 50005
#define mod 1000000007
ll ni;
int a,b,c;
int n,q;

ll tree[N<<2];
ll num[N];

void PushUp(int rt){
tree[rt]=tree[rt<<1]*tree[rt<<1|1];
tree[rt]%=mod;
}
void build(int l,int r,int rt){
    if(l==r){
        tree[rt]=num[l];
        return;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    PushUp(rt);
}
ll update(int L,ll c,int l,int r,int rt){

if(l==r){
    tree[rt]=c;
    return tree[rt];
}
int m=(r+l)>>1;
if(L<=m) update(L,c,l,m,rt<<1);
 else update(L,c,m+1,r,rt<<1|1);
PushUp(rt);
}

ll query(int L,int R,int l,int r,int rt){

if(L<=l&&R>=r){

    return tree[rt];
}
ll ans=1;
int m=(l+r)>>1;
if(L<=m){
    ans*=query(L,R,l,m,rt<<1);
    ans%=mod;
}
if(R>m)
{
    ans*=query(L,R,m+1,r,rt<<1|1);
    ans%=mod;
}

return ans;

}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--){
    memset(tree,1,sizeof(tree));
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf("%lld",&num[i]);
    }

    build(1,n,1);
    scanf("%d",&q);
    for(int i=0;i<q;i++){
        scanf("%d",&c);
        ll x;
        if(c==0){
                scanf("%d%d",&a,&b);
        printf("%lld\n",query(a,b,1,n,1));
        }else{
          scanf("%d%lld",&a,&x);
           update(a,x,1,n,1);
        }
    }
    
    }
    return 0;
}
/*
0  1 2
0  1 3
0  1 4
0  2 7

1  2 1
1  3 1

0  1 2
0  1 3
0  1 4
0  2 7
*/

D 区间不同值求和

相关文章

  • 算法模板(七) 线段树

    线段树单点操作 线段树区间操作

  • 数据结构-线段树

    实现一个线段树 下面实现的线段树,有三个功能: 把数组构建成一颗线段树 线段树的修改 线段树的查询 303号问题 ...

  • 线段树系列之——区间更新

    第三篇线段树了——重点不在于解决题目,通过题目理解线段树才是重点 前面写了一篇关于线段树的单点更新,线段树的单点更...

  • 线段树模板

    线段树 线段树基本概念 概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组)...

  • 线段树专题整理

    待更新 线段树讲解(未读)线段树模板(未读) 模板 求区间总和 A - 敌兵布阵 HDU - 1166 题意 线段...

  • 线段树 02 构建线段树

    构建线段树 线段树的每个节点除了天然的对应一段长度外,不一定赋予其上的意义就是区间元素的和,所以两个节点向上汇聚成...

  • 线段树(区间树)

    线段树:线段树是一种二叉树,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。线段树适用于不变...

  • 线段树

    专题 B线段树求逆序对 C[] D 区间不同值求和

  • 线段树

    [toc] 线段树 实现问题:常用于求数组区间最小值 时间复杂度:(1).建树复杂度:nlogn。(2).线段树算...

  • 线段树

    参考网址:https://www.jianshu.com/p/91f2c503e62f 使用线段树的原因 原来的需...

网友评论

      本文标题:线段树

      本文链接:https://www.haomeiwen.com/subject/mipojftx.html