POJ 3468 区间查询区间修改 伸展树
来源:互联网 发布:c程编程分解质因数 编辑:程序博客网 时间:2024/05/21 09:50
题意:
n个数,有两种操作,一种是查询区间和,另一种是在区间上每一个数加上v。
把bake爷的数组版改造成了结构体版。。
#include<stdio.h>#include<string.h>#include<vector>#include<iostream>#include<queue>using namespace std;#define ll long long#define N 100105#define inf 100000000#define L(id) tree[id].ch[0]#define R(id) tree[id].ch[1]#define Father(id) tree[id].fa#define Mid(x,y) ((x+y)>>1)ll num[N];//序列struct Node{ll ch[2], fa, size;ll val, sum, add;}tree[N];ll tot, root;void Newnode(ll& id, ll fa, ll val){id = ++tot;Father(id) = fa;tree[id].sum = tree[id].val = val;tree[id].add = 0;tree[id].size = 1;L(id) = R(id) = 0;}void push_down(ll id){if(tree[id].add){tree[id].val += tree[id].add;tree[L(id)].sum += tree[id].add * tree[L(id)].size;tree[R(id)].sum += tree[id].add * tree[R(id)].size;tree[L(id)].add += tree[id].add;tree[R(id)].add += tree[id].add;tree[id].add = 0;}}void push_up(ll id){tree[id].size = tree[L(id)].size+tree[R(id)].size +1;tree[id].sum = tree[L(id)].sum+tree[R(id)].sum + tree[id].val;}void rotate(ll id,ll kind){ //kind=0表示左旋,kind=1表示右旋ll y = Father(id);push_down(id); push_down(y);tree[y].ch[kind^1] = tree[id].ch[kind];Father( tree[id].ch[kind] ) = y;if(Father(y))tree[Father(y)].ch[R(Father(y))==y] = id;Father(id) = Father(y);tree[id].ch[kind] = y;Father(y) = id;push_up(y);}void splay(ll id, ll goal){push_down(id);while(Father(id) != goal){if(Father( Father(id) ) == goal)rotate(id,L( Father(id) ) == id);else{int y = Father(id); //y为父节点int kind = L( Father(y) ) == y;if(tree[y].ch[kind] == id){rotate(id,kind^1);rotate(id,kind);}else{rotate(y,kind);rotate(id,kind);}}}push_up(id);if(goal == 0) root = id;}void rotateto(ll k, ll goal){ //把第k个节点转到goal下ll id = root;push_down(id);while(tree[L(id)].size != k){if(tree[L(id)].size > k)id = L(id);else{k -= (tree[L(id)].size + 1);id = R(id);}push_down(id);}splay(id, goal);}ll query(ll l, ll r){rotateto(l-1, 0);rotateto(r+1, root);return tree[L( R(root) )].sum;}void update(ll l, ll r, ll v){rotateto(l-1, 0);rotateto(r+1,root);ll tmp = L( R(root) );tree[tmp].add += v;tree[tmp].sum += (ll)tree[tmp].size*v;}void build(ll l, ll r, ll& id, ll fa){if(l > r)return ;int mid = Mid(l,r);Newnode(id,fa,num[mid]);build(l,mid-1,L(id),id);build(mid+1,r,R(id),id);push_up(id);}ll n, q;void init(){for(ll i = 0; i < n; i++)scanf("%lld",&num[i]);root = tot = 0;Father(0) = L(0) = R(0) = tree[0].size = 0;tree[0].sum = tree[0].val = 0;Newnode(root, 0, -1);Newnode(R(root), root, -1);tree[root].size = 2;build(0, n-1, L( R(root) ), R(root));push_up(R(root));push_up(root);}int main(){ll l, r, v;char str[5];scanf("%lld %lld",&n,&q);init();while(q--){scanf("%s",str);scanf("%lld%lld",&l,&r);if(str[0] == 'Q')printf("%lld\n",query(l,r));else{scanf("%lld",&v);update(l,r,v);}}return 0;}
0 0
- POJ 3468 区间查询区间修改 伸展树
- poj 3468 区间修改查询 解题报告
- 模板(线段树 + 树状数组 + 区间修改 + 区间查询)eg:POJ 3468
- POJ-3468 A Simple Problem with Integers (线段树 入门题 区间修改 区间查询)
- 区间修改,区间查询
- 伸展树(插入区间,修改区间,区间置数,区间反转,区间求和,连续最大和)BZOJ1500
- 线段树区间修改+区间查询
- 线段树(区间修改,区间查询)
- [模板]-线段树-区间修改 + 区间查询
- POJ 3468 线段树 区间更新区间查询
- POJ 3468 (线段树,区间更新,查询区间)
- POJ-3468(线段树区间更新区间查询)
- poj 3468:zkw树区间修改
- POJ 2155 Matrix 二维线段树 区间修改 单点查询
- POJ 2155 二维线段树 修改区间查询点
- [线段树][区间修改&&查询]
- POJ 3468 A Simple Problem with Integers 树状数组 区间修改 区间查询
- POJ 3468 A Simple Problem with Integers 树状数组 区间修改 区间查询
- 启动apache时出现httpd: Could not reliably determine the server
- JSP入门及MyEclipse的使用
- DevExpress中的lookupedit的使用方法详解
- LINUX下挂载exfat格式u盘或移动硬盘
- 微信公众号如何接受图片与发送图片
- POJ 3468 区间查询区间修改 伸展树
- CocoaPods安装和使用教程
- Hibernate4实战之Hibernate4注解零配置
- makefile1
- 潜藏的冷,不觉的就笑了
- iOS 开发百问(1)
- spool命令的使用
- 逗B久了,看到自己就想笑
- Binary Tree Maximum Path Sum