1. 程式人生 > >線段樹模板:點修改,區間修改

線段樹模板:點修改,區間修改

#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>
#include<cmath>
#include<bitset>
#include<sstream>
#include<stack>
using namespace std;
#define INF 0x7fffffff
typedef long long ll;
const int maxnode=1<<17;

int _sum,_min,_max,op,qL,qR,v;
struct IntervalTree
{
    int sumv[maxnode],maxv[maxnode],minv[maxnode],setv[maxnode];

    //維護資訊
    void maintain(int o,int L,int R){
        int lc=2*o,rc=2*o+1;
        if(R>L){
            sumv[o]=sumv[lc]+sumv[rc];
            minv[o]=min(minv[lc],minv[rc]);
            maxv[o]=max(maxv[lc],maxv[rc]);
        }
        if(setv[o]>=0){
            minv[o]=maxv[o]=setv[o];
            sumv[o]=setv[o]*(R-L+1);
        }
    }

    //標記傳遞
    void pushdown(int o){
        int lc=2*o,rc=2*o+1;
        if(setv[o]>=0){
            //本結點有標記才傳遞。注意本題中set值非負
            setv[lc]=setv[rc]=setv[o];
            setv[o]=-1;//清除本結點標記
        }
    }

    //更新資訊
    void update(int o,int L,int R){
        int lc=2*o,rc=2*o+1;
        if(qL<=L&&R<=qR){
            //標記修改
            setv[o]=v;
        }
        else{
            pushdown(o);
            int M=L+(R-L)/2;
            if(qL<=M) update(lc,L,M); else maintain(lc,L,M);
            if(qR>M) update(rc,M+1,R); else maintain(rc,M+1,R);
        }
        maintain(o,L,R);
    }

    void query(int o,int L,int R){
        if(setv[o]>=0){
            //遞迴邊界1:有set標記
            _sum+=setv[o]*(min(R,qR)-max(L,qL)+1);
            _min=min(_min,setv[o]);
            _max=max(_max,setv[o]);
        }
        else if(qL<=L&&qR>=R){
            //遞迴邊界2:邊界區間
            //此邊界區間沒有被任何set操作影響
            _sum+=sumv[o];
            _min=min(_min,minv[o]);
            _max=max(_max,maxv[o]);
        }
        else{
            //遞迴統計
            int M=L+(R-L)/2;
            if(qL<=M) query(2*o,L,M);
            if(qR>M) query(2*o+1,M+1,R);
        }
    }
};

IntervalTree tree;

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)==2){
        memset(&tree,0,sizeof(tree));
        memset(tree.setv,-1,sizeof(tree.setv));
        tree.setv[1]=0;
        while(m--){
            scanf("%d%d%d",&op,&qL,&qR);
            if(op==1){
                scanf("%d",&v);
                tree.update(1,1,n);
            }
            else{
                _sum=0;_min=INF;_max=-INF;
                tree.query(1,1,n);
                printf("%d %d %d\n",_sum,_min,_max);
            }
        }
    }
    return 0;
}