POJ_3468 A Simple Problem with Integers(线段树区间修改+附线段树模板)

来源:互联网 发布:淘宝直播入口在哪 编辑:程序博客网 时间:2024/06/15 14:40

题目链接

题目大意

中文题目

解决

  1. 线段树区间修改+求和查询的裸题
  2. 直接附上代码^_^
#include <algorithm>#include <iostream>#include <cstring>#include <vector>#include <cstdio>#include <string>#include <cmath>#include <queue>#include <set>#include <map>#include <complex>using namespace std;typedef long long ll;typedef long double db;typedef pair<int,int> pii;typedef vector<int> vi;#define de(x) cout << #x << "=" << x << endl#define rep(i,a,b) for(int i=a;i<(b);++i)#define all(x) (x).begin(),(x).end()#define sz(x) (int)(x).size()#define mp make_pair#define pb push_back#define fi first#define se second#define E 1e-6#define INF 0x3f3f3f3f#pragma comment(linker, "/STACK:1024000000,1024000000")void open(){freopen("data.txt","r",stdin);}void out(){freopen("out.txt","w",stdout);}const int maxn = 1e5+5;const int MOD = 1e9 + 7;int a[maxn];ll st[maxn<<2],add[maxn<<2];void build(int o,int l,int r){    if(l==r)    st[o] = a[l];    else{        int m = (l+r)>>1;        build(o<<1,l,m);        build((o<<1)|1,m+1,r);        st[o] = st[o<<1]+st[(o<<1)|1];    }}void pushup(int o){    st[o] = st[o<<1]+st[(o<<1)|1];}void pushdown(int o,int l,int r){    if(add[o]){        add[o<<1]+=add[o];        add[(o<<1)|1]+=add[o];        int m = (l+r)>>1;        st[o<<1]+=add[o]*(m-l+1);        st[(o<<1)|1]+=add[o]*(r-m);        add[o] = 0;    }}void update(int o,int l,int r,int al,int ar,int addv){    if(al<=l&&ar>=r){        add[o]+=addv;        st[o]+=addv*(r-l+1);    }    else{        pushdown(o,l,r);        int m = (l+r)>>1;        if(al<=m)   update(o<<1,l,m,al,ar,addv);        if(ar>=m+1) update((o<<1)|1,m+1,r,al,ar,addv);        pushup(o);    }}ll query(int o,int l,int r,int ql,int qr){    if(ql<=l && qr>=r)  return st[o];    pushdown(o,l,r);    int m = (l+r)>>1;    ll ans = 0;    if(ql<=m)   ans+=query(o<<1,l,m,ql,qr);    if(qr>=m+1) ans+=query((o<<1)|1,m+1,r,ql,qr);    return ans;}int main(){    int n,m;    scanf("%d%d",&n,&m);    rep(i,1,n+1) scanf("%d",&a[i]);    build(1,1,n);    rep(i,0,m){        char c;        int u,v,w;        getchar();        scanf("%c",&c);        if(c=='Q'){            scanf("%d%d",&u,&v);            printf("%lld\n",query(1,1,n,u,v));        }        else{            scanf("%d%d%d",&u,&v,&w);            update(1,1,n,u,v,w);        }    }    return 0;}

个人总结的线段树模板

int a[maxn] , st[maxn<<2] , change[maxn<<2] , add[maxn<<2];//  st数组用于保存信息,可以是区间最大值、区间最小值、区间和等void build(int o,int l,int r){    if(l==r) st[o] = a[l];    else{        int m = (l+r)>>1;        build(o<<1,l,m);        build((o<<1)|1,m+1,r);        st[o] = st[o<<1]+st[(o<<1)|1];    //  st[o] = max(st[o<<1] , st[(o<<1)|1]);    //  st[o] = min(st[o<<1] , st[(o<<1)|1]);    }}/*  ——————————单点更新——————————void update(int o,int l,int r,int ind,int ans){    if(l==r)    st[o] = ans;    else{        int m = (l+r)>>1;        if(ind<=m)  update(o<<1,l,m,ind,ans);        else        update((o<<1)|1,m+1,r,ind,ans);        st[o] = st[o<<1]+st[(o<<1)|1];    //  st[o] = max(st[o<<1] , st[(o<<1)|1]);    //  st[o] = min(st[o<<1] , st[(o<<1)|1]);    }}int query(int o,int l,int r,int ql,int qr){    if(ql>r||qr<l)      return -1;           //返回一个对查询结果无关的量    if(ql<=1&&qr>=r)    return st[o];    int m = (l+r)>>1;    int p1 = query(o<<1,l,m,ql,qr) , p2 = query((o<<1)|1,m+1,r,ql,qr);    return max(p1,p2);}    ————————————END————————     *///  ——————以下区间修改——————void pushup(int o){    st[o] = st[o<<1] + st[(o<<1)|1];//  st[o] = max(st[o<<1] , st[(o<<1)|1]);//  st[o] = min(st[o<<1] , st[(o<<1)|1]);}//  ——————————区间加值——————————void pushdown(int o,int l,int r)        //pushdown_区间加值{    if(add[o]){                         //当前节点上有待更新值        add[o<<1]+=add[o];              //传递至左子节点        add[(o<<1)|1]+=add[o];          //传递至右子节点        int m = (l+r)>>1;        st[o<<1]+=add[o]*(m-l+1);        st[(o<<1)|1]+=add[o]*(r-m);        add[o] = 0;                     //父亲节点更新信息删除    }}//  用于区间加值,配合add数组使用void update(int o,int l,int r,int al,int ar,int addv){    if(al<=l && ar>=r){                 //当前区间被覆盖        add[o]+=addv;        st[o]+=addv*(r-l+1);    }    else{        pushdown(o,l,r);                //当前节点更新信息传递至下一层        int m = (l+r)>>1;        if(al<=m)   update(o<<1,l,m,al,ar,addv);        if(ar>=m+1) update((o<<1)|1,m+1,r,al,ar,addv);        pushup(o);    }}//  ——————————END——————————————/*  ————————区间改值——————————void pushdown(int o,int l,int r)        //pushdown_区间改值{    if(change[o]){        int s = change[o];        change[o<<1] = s;        change[(o<<1)|1] = s;        int m = (l+r)>>1;        st[o<<1] = (m-l+1)*s;        st[(o<<1)|1] = (r-m)*s;        change[o] = 0;    }}//  用于区间改值,配合change数组使用void update(int o,int l,int r,int sl,int sr,int s){    if(sl<=l && sr>=r){        change[o] = s;        st[o] = (r-l+1)*s;    }    else{        pushdown(o,l,r);        int m = (l+r)>>1;        if(sl<=m)   update(o<<1,l,m,sl,sr,s);        if(sr>=m+1) update((o<<1)|1,m+1,r,sl,sr,s);        pushup(o);    }}    ——————————END————————————   */int query(int o,int l,int r,int ql,int qr)          //区间修改问题查询通用{    if(ql<=l && qr>=r) return st[o];                //当前节点覆盖区间即为所需查询区间    pushdown(o,l,r);                                //将待查询节点的更新信息传递给子节点    int m = (l+r)>>1;    ll ans = 0;    if(ql<=m)   ans+=query(o<<1,l,m,ql,qr);         //查询区间与当前节点左子节点有交集,结果加上左子节点查询结果    if(qr>=m+1) ans+=query((o<<1)|1,m+1,r,ql,qr);   //查询区间与当前节点右子节点有交集,结果加上右子节点查询结果    return ans;}
阅读全文
0 0
原创粉丝点击