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
原创粉丝点击