题意:
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; }