题意:有两种操作: 1. C l r x: 区间[l,r]的数加x。 2. Q l r : 查询区间[l,r]的和。
思路:线段树的裸题,只是为了练习splay。详见代码:
/*********************************************************
file name: poj3468.cpp
author : kereo
create time: 2015年01月28日 星期三 15时03分07秒
*********************************************************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<set>
#include<map>
#include<vector>
#include<stack>
#include<cmath>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
const int sigma_size=26;
const int N=100+50;
const int MAXN=100000+50;
const int inf=0x3fffffff;
const double eps=1e-8;
const int mod=100000000+7;
#define L(x) (x->ch[0])
#define R(x) (x->ch[1])
#define PII pair<int, int>
#define mk(x,y) make_pair((x),(y))
int n,m,cnt,top;
int st[MAXN];
char str[N];
ll num[MAXN];
struct node{
int sz;
ll val,sum,tag;
node *fa,*ch[2];
}nod[MAXN],nil,*root,*null;
struct Splay{
void rotate(node *x,int d){
node *y=x->fa;
push_down(y); push_down(x);
y->ch[d^1]=x->ch[d];
if(x->ch[d]!=null) x->ch[d]->fa=y;
x->fa=y->fa;
if(y->fa!=null){
int d1=y->fa->ch[0] == y ? 0 : 1;
y->fa->ch[d1]=x;
}
y->fa=x; x->ch[d]=y;
push_up(y);
}
void splay(node *x,node *fa){
while(x->fa!=fa){
push_down(x);
node *y=x->fa;
if(y->fa == fa){
int d=y->ch[0] == x ? 1 : 0;
rotate(x,d);
}
else{
int d=y->fa->ch[0] == y ? 1 : 0;
if(y->ch[d] == x){
rotate(x,d^1); rotate(x,d);
}
else{
rotate(y,d); rotate(x,d);
}
}
}
push_up(x);
if(fa == null) root=x;
}
void rotateto(int k,node *fa){
node *rt=root;
push_down(rt);
while(L(rt)->sz!=k){
if(L(rt)->sz>k)
rt=L(rt);
else{
k-=(L(rt)->sz+1);
rt=R(rt);
}
push_down(rt);
}
splay(rt,fa);
}
void init(){
cnt=top=0;
nil.sz=nil.val=nil.sum=nil.tag=0;
null=&nil; root=null;
newnode(root,null,0);
newnode(R(root),root,0);
for(int i=1;i<=n;i++)
scanf("%lld",&num[i]);
build(L(R(root)),R(root),1,n);
push_up(R(root)); push_up(root);
}
void newnode(node *&x,node *fa,int val){
if(top)
x=&nod[st[--top]];
else
x=&nod[++cnt];
x->sz=1; x->val=x->sum=val;
x->tag=0; x->fa=fa; x->ch[0]=x->ch[1]=null;
}
void push_down(node *rt){
if(rt->tag){
rt->val+=rt->tag;
L(rt)->tag+=rt->tag; R(rt)->tag+=rt->tag;
L(rt)->sum+=L(rt)->sz*rt->tag;
R(rt)->sum+=R(rt)->sz*rt->tag;
rt->tag=0;
}
}
void push_up(node *rt){
rt->sz=L(rt)->sz+R(rt)->sz+1;
rt->sum=rt->val+L(rt)->sum+R(rt)->sum;
}
void build(node *&rt,node *fa,int l,int r){
if(l>r)
return ;
int mid=(l+r)>>1;
newnode(rt,fa,num[mid]);
build(L(rt),rt,l,mid-1); build(R(rt),rt,mid+1,r);
push_up(rt);
}
void update(int l,int r,ll x){
rotateto(l-1,null);
rotateto(r+1,root);
node *rt=L(R(root));
rt->tag+=x;
rt->sum+=rt->sz*x;
}
ll query(int l,int r){
rotateto(l-1,null);
rotateto(r+1,root);
return L(R(root))->sum;
}
}spt;
int main(){
//freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m)){
spt.init();
while(m--){
scanf("%s",str);
if(str[0] == 'C'){
int l,r;
ll x;
scanf("%d%d%lld",&l,&r,&x);
spt.update(l,r,x);
}
else{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",spt.query(l,r));
}
}
}
return 0;
}