题意 : n个数,成段更新,区间求和 。
思路 : 线段树可以做,用splay做感觉好辛苦 ... 吃力不讨好 ... 纯粹就是当做熟悉splay用的
要用splay访问一个区间[L,R], 我们只要把 L-1 splay 到根 , 然后把 R + 1 splay 到根的右子树
那么 根的右子树的左子树就是[ L , R ] 这个区间了
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define MAXN 100005
#define INF 0x3f3f3f3f
#define keyNode ( ch[ch[root][1]][0] )
#define ls(x) ( ch[x][0] )
#define rs(x) ( ch[x][1] )
typedef long long LL ;
int n , m ;
struct Splay{
int tot ;
int ch[MAXN][2] ;
int pre[MAXN] ;
int sz[MAXN] ;
LL sum[MAXN] ;
LL val[MAXN] ;
LL add[MAXN] ;
LL a[MAXN] ;
int root ;
// 旋转
void Rotate( int x , int op ) {
int y = pre[x] ;
push_down( y ) ;
push_down( x ) ;
if( pre[y] ) {
ch[pre[y]][ch[pre[y]][1] == y ] = x ;
}
pre[x] = pre[y] ;
pre[y] = x ;
ch[y][op] = ch[x][op^1] ;
if( pre[ch[x][op^1]] )
pre[ch[x][op^1]] = y ;
ch[x][op^1] = y ;
push_up(y) ;
}
// 伸展
void splay( int x , int goal ) {
push_down( x ) ;
while( pre[x] != goal ) {
int y = pre[x] ;
if( pre[y] == goal ) {
Rotate( x , ch[y][1] == x ) ;
}else{
int y = pre[x] ;
int op = rs(y) == x ;
if( ch[pre[y]][op] == y ) {
Rotate( y , op ) ;
Rotate( x , op ) ;
}else{
Rotate( x , op ) ;
Rotate( x , op ^ 1 ) ;
}
}
}
push_up( x ) ;
if( goal == 0 ) root = x ;
}
// 把第k个伸展至goal下
void RotateTo( int k , int goal ) {
int x = root ;
push_down( x ) ;
while( sz[ls(x)] != k ) {
if( k < sz[ls(x)] ) {
x = ls(x) ;
}else{
k -= sz[ls(x)] + 1 ;
x = rs(x) ;
}
push_down( x ) ;
}
splay( x , goal ) ;
}
// 创建一个结点
void makenode( int &x , int fa , LL v ) {
x = tot ++ ;
pre[x] = fa ;
ls(x) = rs(x) = 0 ;
sz[x] = 1 ;
sum[x] = val[x] = v ;
add[x] = 0 ;
}
// 子节点信息向上传
void push_up( int x ) {
sz[x] = sz[ls(x)] + sz[rs(x)] + 1 ;
sum[x] = add[x] + val[x] + sum[ls(x)] + sum[rs(x)] ;
}
// 父节点信息向下传
void push_down( int x ) {
if( add[x] ) {
val[x] += add[x] ;
add[ls(x)] += add[x] ;
add[rs(x)] += add[x] ;
sum[ls(x)] += sz[ls(x)] * add[x] ;
sum[rs(x)] += sz[rs(x)] * add[x] ;
add[x] = 0 ;
}
}
// 创建区间
void build( int l , int r , int & x , int fa ) {
if( l > r ) return ;
int m = ( l + r ) >> 1 ;
makenode( x , fa , a[m] ) ;
build( l , m - 1 , ls(x) , x ) ;
build( m + 1 , r , rs(x) , x ) ;
push_up( x ) ;
}
// 查询区间信息
LL query( int l , int r ) {
RotateTo( l - 1 , 0 ) ;
RotateTo( r + 1 , root ) ;
return sum[keyNode] ;
}
// 更新区间信息
LL update( int l , int r , int c ) {
RotateTo( l - 1 , 0 ) ;
RotateTo( r + 1 , root ) ;
add[keyNode] += c ;
sum[keyNode] += sz[keyNode] * c ;
LL ans = sum[keyNode] ;
splay( keyNode , 0 ) ;
return ans ;
}
// 初始化splay
void init(){
//=============== 初始化边界 ================
tot = 1 ;
makenode( root , 0 , 0 ) ;
makenode( rs(root) , root , 0 ) ;
sz[root] ++ ;
//=============== 初始化区间 ================
for( int i = 1 ; i <= n ; i ++ ) {
scanf( "%lld" , &a[i] ) ;
}
build( 1 , n , keyNode , rs(root) ) ;
push_up( rs(root) ) ;
push_up( root ) ;
}
}s;
int main(){
while( scanf( "%d%d" , &n , &m ) != EOF ) {
s.init() ;
while( m -- ) {
char op[10] ;
scanf( "%s" , op ) ;
if( op[0] == 'Q' ) {
int l , r ;
scanf( "%d%d" , &l ,&r ) ;
printf( "%lld\n" , s.query( l , r ) ) ;
}else{
int l , r , c ;
scanf( "%d%d%d" , &l , &r , &c ) ;
s.update( l , r , c ) ;
}
}
}
return 0 ;
}