http://poj.org/problem?id=3468
题意:给出一段区间,并给出每个点的初值,C l, r, val 表示给 l, r 这段区间每个点都加上 val (val可以数负数), Q l, r 表示询问 l, r 区间的和。
思路:普通的线段树就能搞定。
线段树(3547ms):
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
typedef long long ll;
const ll maxn = 100005;
struct Tree{
ll sum;
ll l, r, lazy;
inline void SetTree(ll l, ll r, ll lazy, ll sum)
{
this->l = l;
this->r = r;
this->lazy = lazy;
this->sum = sum;
}
};
ll n, m;
ll mapn[maxn];
Tree tr[maxn << 2];
ll BuildTree(ll rt, ll l, ll r)
{
if(l == r){
tr[rt].SetTree(l, r, 0, mapn[l]);
return mapn[l];
}
tr[rt].SetTree(l, r, 0, 0);
ll mid = (l + r) >> 1;
tr[rt].sum = BuildTree(rt << 1, l, mid) + BuildTree(rt << 1 | 1, mid + 1, r);
return tr[rt].sum;
}
void PushDown(ll rt)
{
if(!tr[rt].lazy || tr[rt].l == tr[rt].r)
return ;
tr[rt << 1].lazy += tr[rt].lazy;
tr[rt << 1 | 1].lazy += tr[rt].lazy;
tr[rt << 1].sum += ll(tr[rt << 1].r - tr[rt << 1].l + 1) * tr[rt].lazy;
tr[rt << 1 | 1].sum += ll(tr[rt << 1 | 1].r - tr[rt << 1 | 1].l + 1) * tr[rt].lazy;
tr[rt].lazy = 0;
}
ll Updata(ll rt, ll l, ll r, ll val)
{
PushDown(rt);
if(tr[rt].l > r || tr[rt].r < l)
return tr[rt].sum;
if(tr[rt].l >= l && tr[rt].r <= r){
tr[rt].lazy += val;
tr[rt].sum += ll(tr[rt].r - tr[rt].l + 1) * val;
return tr[rt].sum;
}
tr[rt].sum = Updata(rt << 1, l, r, val) + Updata(rt << 1 | 1, l, r, val);
return tr[rt].sum;
}
ll Query(ll rt, ll l, ll r)
{
PushDown(rt);
if(tr[rt].l > r || tr[rt].r < l)
return 0;
if(tr[rt].l >= l && tr[rt].r <= r)
return tr[rt].sum;
return Query(rt << 1, l, r) + Query(rt << 1 | 1, l, r);
}
int main()
{
char str[10];
ll l, r, val;
while(~scanf("%I64d%I64d", &n, &m)){
for(ll i = 1; i <= n; i++){
scanf("%I64d", &mapn[i]);
}
BuildTree(1, 1, n);
while(m --){
scanf("%s%I64d%I64d", str, &l, &r);
if(str[0] == 'C'){
scanf("%I64d", &val);
Updata(1, l, r, val);
}else{
printf("%I64d\n", Query(1, l, r));
}
}
}
return 0;
}
Splay树(4829ms):
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 100005;
typedef long long ll;
struct Tree{
ll pre, chd[2];
ll Size, lazy, val, sum;
void SetTree(ll pre, ll chd0, ll chd1, ll Size, ll lazy, ll val, ll sum){
this->pre = pre;
this->chd[0] = chd0;
this->chd[1] = chd1;
this->Size = Size;
this->lazy = lazy;
this->val = val;
this->sum = sum;
}
};
ll n, m;
Tree tr[maxn];
ll F(ll rt){
return tr[tr[rt].pre].chd[1] == rt;
}
void PushUp(ll rt)
{
tr[tr[rt].chd[0]].pre = rt;
tr[tr[rt].chd[1]].pre = rt;
tr[rt].Size = tr[tr[rt].chd[0]].Size + tr[tr[rt].chd[1]].Size + 1;
tr[rt].sum = tr[tr[rt].chd[0]].sum + tr[tr[rt].chd[1]].sum + tr[rt].val;
}
void PushDown(ll rt)
{
if(!tr[rt].lazy)
return ;
if(tr[rt].chd[0]){
tr[tr[rt].chd[0]].val += tr[rt].lazy;
tr[tr[rt].chd[0]].lazy += tr[rt].lazy;
tr[tr[rt].chd[0]].sum += tr[rt].lazy * tr[tr[rt].chd[0]].Size;
}
if(tr[rt].chd[1]){
tr[tr[rt].chd[1]].val += tr[rt].lazy;
tr[tr[rt].chd[1]].lazy += tr[rt].lazy;
tr[tr[rt].chd[1]].sum += tr[rt].lazy * tr[tr[rt].chd[1]].Size;
}
tr[rt].lazy = 0;
}
void Rotate(ll rt)
{
ll chd = F(rt);
ll pre = tr[rt].pre;
tr[rt].pre = tr[pre].pre;
tr[tr[pre].pre].chd[F(pre)] = rt;
tr[pre].chd[chd] = tr[rt].chd[!chd];
tr[rt].chd[!chd] = pre;
PushUp(pre);
PushUp(rt);
}
ll Splay(ll rt, ll rw)
{
while(tr[rw].pre != rt){
ll pre = tr[rw].pre;
if(F(rw) != F(pre) || tr[pre].pre == rt){
Rotate(rw);
}else{
Rotate(pre);
Rotate(rw);
}
}
if(rt)
PushUp(rt);
return rw;
}
ll Find(ll rt, ll pos)
{
ll ret = rt;
PushDown(rt);
if(tr[tr[rt].chd[0]].Size == pos - 1)
ret = rt;
else if(tr[tr[rt].chd[0]].Size >= pos)
ret = Find(tr[rt].chd[0], pos);
else
ret = Find(tr[rt].chd[1], pos - tr[tr[rt].chd[0]].Size - 1);
return ret;
}
ll BuildTree(ll Size)
{
for(ll i = 1; i < Size; i++){
tr[i].SetTree(i - 1, 0, i + 1, Size - i + 1, 0, 0, 0);
}
tr[0].SetTree(0, 0, 0, 0, 0, 0, 0);
tr[Size].SetTree(Size - 1, 0, 0, 1, 0, 0, 0);
return 1;
}
int main()
{
char str[5];
ll l, r, val;
while(~scanf("%d%d", &n, &m)){
ll rt = BuildTree(n + 2);
for(ll i = 1; i <= n; i++){
scanf("%I64d", &tr[i + 1].val);
}
rt = Splay(0, n + 2);
while(m--){
scanf("%s%I64d%I64d", str, &l, &r);
rt = Splay(0, Find(rt, l));
Splay(rt, Find(rt, r + 2));
if(str[0] == 'C'){
scanf("%I64d", &val);
tr[tr[tr[rt].chd[1]].chd[0]].val += val;
tr[tr[tr[rt].chd[1]].chd[0]].lazy += val;
tr[tr[tr[rt].chd[1]].chd[0]].sum += tr[tr[tr[rt].chd[1]].chd[0]].Size * val;
PushUp(tr[rt].chd[1]);
PushUp(rt);
}else{
printf("%I64d\n", tr[tr[tr[rt].chd[1]].chd[0]].sum);
}
}
}
return 0;
}