线段树

懒标记的修改时间和下传时间:

wa:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<cstdlib>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+5;
const int INF=2147483647;
inline int read(){
    int a=0;bool b=1;char x=getchar();
    while(x<'0'||'9'<x){
        if(x=='-')b=0;
        x=getchar();
    }
    while('0'<=x&&x<='9'){
        a=(a<<1)+(a<<3)+x-'0';
        x=getchar();
    }
    return b ? a : -a ;
}
int n,m,a[maxn];
struct Node{
    int l;int r;LL sum;LL addsum;
    inline void deal(){
        sum+=addsum*(r-l+1);
        addsum=0ll;
        return;
    }
    inline void print(){
        printf("%d %d %lld %lld\n",l,r,sum,addsum);
        return;
    }
}L[maxn*4];
inline void down(int k){
    if(L[k].l!=L[k].r){
    L[k<<1].addsum+=L[k].addsum;
    L[(k<<1)+1].addsum+=L[k].addsum;
    }
    L[k].deal();
    return;
}
void build(int k,int l,int r){
    if(l==r)L[k]={l,r,a[l]};
    else{
        int mid=(l+r)>>1;
        build((k<<1),l,mid);
        build((k<<1)+1,mid+1,r);
        L[k]={l,r,L[(k<<1)].sum+L[(k<<1)+1].sum};
    }
}
void modify(int k,int l,int r,int x){
    if(l<=L[k].l&&L[k].r<=r){
        L[k].print();
        L[k].addsum+=(LL)x;
        down(k);
        L[k].print();
    }
    else{
        int mid=(L[k].l+L[k].r)>>1;
        LL add1=0ll,add2=0ll;
        if(l<=mid){
        add1=L[k<<1].sum;
        modify((k<<1),l,r,x);
        add1=L[k<<1].sum-add1;
        }
        if(mid<r){
        add2=L[(k<<1)+1].sum;
        modify((k<<1)+1,l,r,x);
        add2=L[(k<<1)+1].sum-add2;
        }
        
        L[k].sum+=(add1+add2);
        //叶子节点保证必须是对的,有时候会有问题
//懒标记不能重复加,修改完一个区间,其子节点的懒标记在下次修改时不能更新自己
    }
}
LL query(int k,int l,int r){
    if(L[k].addsum)down(k);
    //保证每次遇到的节点都是最新的
    L[k].print();
    L[12].print();
    if(l<=L[k].l&&L[k].r<=r)return L[k].sum;
    int mid=(L[k].l+L[k].r)>>1;
    LL ans=0ll;
    if(l<=mid)ans+=query((k<<1),l,r);
    if(mid<r)ans+=query((k<<1)+1,l,r);
    return ans;
}

int main(){
    freopen("1.out","w",stdout);
    n=read();
    for(int i=1;i<=n;i++)a[i]=read();
    build(1,1,n);
    m=read();
    for(int i=1,b,l,r,x;i<=m;i++){
        b=read();
        if(b==1){
            l=read();r=read();x=read();
            modify(1,l,r,x);
        }
        else{
            l=read();r=read();
            printf("%lld\n",query(1,l,r));
        }
    }
    return 0;
}
/*
10
1 2 3 4 5 6 1 2 3 4
  4 4              
    5 5 5 5 5
  5 5 5 5 5

5
1 2 3 4
2 1 4
1 3 7 5
1 2 6 5
2 1 7
*/

 模板:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cstdlib>
#include<cmath>
using namespace std;
const int maxn=6e4+5;
template <typename T>
inline void read(T &a){

    a=0;T b=1;char x=getchar();
    while(x<'0'||'9'<x){
        if(x=='-')b=-1;
        x=getchar();
    }
    while('0'<=x && x<='9'){
        a=(a<<1)+(a<<3)+x-'0';
        x=getchar();    
    }
    a*=b;
}
char ch[30];
int temp;
template <typename T>
inline void print(T a){
    if(a<0){
        putchar('-');
        a=-a;
    }
    do{
        ch[++temp]= a % 10 + '0';
        a /= 10;
    }while(a);
    while(temp) putchar(ch[temp--]);putchar(' ');
}
template <typename T>
struct Node
{
    int l;int r;T sum;T Min;T Max;T lazy;
    inline void update(const Node &a,const Node &b){
        sum=a.sum+b.sum;
        Min=min(a.Min,b.Min);
        Max=max(a.Max,b.Max);
    }
    inline void add(T x){
        sum+=(r-l+1)*x;Min+=x;Max+=x;
        lazy+=x;
    }
    inline void Print(){
        print(sum);print(Min);print(Max);putchar('\n');
    } 
};
int n,m,a[maxn];
template <typename T>
class Segment_tree
{
    public:
    
        Node<T> L[maxn*4];
        inline void pushdown(int k){
            L[k<<1].add(L[k].lazy);
            L[k<<1|1].add(L[k].lazy);
            L[k].lazy=0;
        }
        Node<T> query(int k,int l,int r){
            if(l<=L[k].l&&L[k].r<=r){
                return L[k];
            }
            else{
                pushdown(k);
                
                int mid=(L[k].l+L[k].r)>>1;
                if(r<=mid)return query(k<<1,l,r);
                if(mid<l)return query(k<<1|1,l,r);
                Node <T>ans;
                ans.update(query(k<<1,l,r),query(k<<1|1,l,r));
                return ans;
            }
        }
        void build(int k,int l,int r){
            if(l==r){
                L[k]={l,r,a[l],a[l],a[l]};
                return;
            }
            else{
                int mid=(l+r)>>1;
                build(k<<1,l,mid);
                build(k<<1|1,mid+1,r);
                L[k]={l,r};
                return L[k].update(L[k<<1],L[k<<1|1]);
            }
        }
        void modify(int k,int l,int r,T x){
            if(l<=L[k].l&&L[k].r<=r){
                return L[k].add(x);
            }
            else{
                pushdown(k);
                
                int mid=(L[k].l+L[k].r)>>1;
                if(l<=mid) modify(k<<1,l,r,x);
                if(mid<r) modify(k<<1|1,l,r,x);
                return L[k].update(L[k<<1],L[k<<1|1]); 
            }
        }
};

Segment_tree<int > s;

int main(){
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
    }
    s.build(1,1,n);
    read(m);
    for(int i=1,b,x,y,z;i<=m;i++){
        read(b);
        if(!b){
            read(x);read(y);read(z);
            s.modify(1,x,y,z);
        }
        else{
            read(x);read(y);
            s.query(1,x,y).Print();
        }
    }
    return 0;
}

灵活使用线段树:

不一定非得标记下传,不一定非得区间合并,注意计算复杂度

#include<cstdio>
#include<algorithm>
#include<cmath>
#define LL long long
using namespace std;
const int maxn=1e5+5;
template<typename T>
inline void read(T &a){
    //!! 引用
    a=0;T b=1;char x=getchar();
    while(x<'0' || '9'<x){
        if(x=='-')b=-1;
        x=getchar();
    }
    while('0'<=x&&x<='9'){
        a=(a<<1)+(a<<3)+x-'0';
        x=getchar();
    }
    a*=b;
}
char ch[30];
int temp;
template<typename T>
inline void print(T a){
    if(a<0){
        putchar('-');
        a=-a;
    }
    do{
        ch[++temp]=a%10+'0';
        a/=10;
    }while(a);
    while(temp)putchar(ch[temp--]);putchar('\n');
}
int n,m;
LL a[maxn];
struct Node{
    int l;int r;LL sum;bool judge;
    //问题特性:几次运算之后就会无法变化&当前节点难以直接算出
    inline void update(const Node&a,const Node&b){
        sum=a.sum+b.sum;
        judge=a.judge & b.judge;
    }
    inline void Print(){
        print(l);print(r);print(sum);print(judge);
    }
}L[maxn*4];
inline void build(int k,int l,int r){
    if(l==r){
        L[k]={l,r,a[l],a[l]==1ll};
    }
    else{
        int mid=(l+r)>>1;
        build(k<<1,l,mid);
        build(k<<1|1,mid+1,r);
        L[k]={l,r};
        
        L[k].update(L[k<<1],L[k<<1|1]);//L[k].Print();putchar('\n');
    }
}
/*inline void pushdown(int k)
{
    L[k<<1].modify(L[k].lazy);
    L[k<<1|1].modify(L[k].lazy);
    L[k].lazy=0;
}*/
//本题为标记上传,标记下传很麻烦
LL query(int k,int l,int r){
    if(l<=L[k].l&&L[k].r<=r){
        return L[k].sum;
    }
    else{
        //if(L[k].lazy)pushdown(k);
        int mid=(L[k].l+L[k].r)>>1;
        LL ans=0;
        if(l<=mid)ans+=query(k<<1,l,r);
        if(mid<r)ans+=query(k<<1|1,l,r);
        return ans;
    }
}
void modify(int k,int l,int r){
    if(L[k].judge)return;
    //all is one ,needn‘t changing
    
    if(L[k].l==L[k].r){
        L[k].sum=sqrt(L[k].sum);
        if(L[k].sum==1ll)L[k].judge=1;
        //修改要都修改,否则吃屎!!!三处使用,只修改两处,瞬间傻B!!! 
    }
    else{
        int mid=(L[k].l+L[k].r)>>1;
        if(r<=mid)modify(k<<1,l,r);
        else if(mid<l)modify(k<<1|1,l,r);
        else {
        modify(k<<1,l,r);
        modify(k<<1|1,l,r);
        }
        
        L[k].update(L[k<<1],L[k<<1|1]);
        //L[k].Print();
    }
}
/*int f[maxn];
int find(int x){return x==f[x] ? x : f[x]=find(f[x]) ;}*/
int main(){
    
    read(n);
    for(int i=1;i<=n;i++){
        read(a[i]);
        //f[i]=i;
    }
    build(1,1,n);
    read(m);
    for(int i=1,k,l,r;i<=m;i++){
        read(k);read(l);read(r);
        if(l>r)swap(l,r);
        
        if(!k){
            modify(1,l,r);
        }
        else{
            print(query(1,l,r));
        }
    }
    return 0;
} 

 

posted @ 2019-05-19 21:10  Tj1  阅读(102)  评论(0编辑  收藏  举报