您的位置:首页 > 其它

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

2017-10-02 20:45 543 查看

题目链接

题目大意

中文题目

解决

线段树区间修改+求和查询的裸题

直接附上代码^_^

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj
相关文章推荐