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; }
相关文章推荐
- 模板(线段树 + 树状数组 + 区间修改 + 区间查询)eg:POJ 3468 - A Simple Problem with Integers
- poj 3468 A Simple Problem with Integers(线段树区间修改+区间求和)
- POJ 3468 A Simple Problem with Integers (线段树区间更新模板)
- POJ 3468 A Simple Problem with Integers(线段树区间修改)
- POJ 3468 - A Simple Problem with Integers(线段树区间更新+模板)
- poj 3468 A Simple Problem with Integers【线段树区间修改】
- POJ-3468-A Simple Problem with Integers(线段树区间修改)
- POJ 3468 A Simple Problem with Integers (线段树区间修改查询)
- A Simple Problem with Integers POJ - 3468 (线段树区间增减,区间查询模板)
- POJ - 3468 - A Simple Problem with Integers 【线段树 区间修改】
- POJ 3468 A Simple Problem with Integers 线段树区间更新 纯模板题
- poj 3468:A Simple Problem with Integers(线段树,区间修改求和)
- POJ 3468 A Simple Problem with Integers (线段树区间更新模板题)
- POJ 3468 A Simple Problem with Integers(线段树区间更新模板题)
- POJ 3468 A Simple Problem with Integers(线段树区间更新模板题)
- poj 3468 A Simple Problem with Integers 线段树模板区间更新
- [省选前题目整理][POJ 3468]A Simple Problem with Integers(线段树区间修改)
- POJ 3468 A Simple Problem with Integers(线段树区间更新,模板题,求区间和)
- POJ - 3468 B - A Simple Problem with Integers 线段树区间更新模板
- POJ 3468 A Simple Problem with Integers 线段树区间修改