线段树基础题,除线段树外至少还有2种做法:树状数组,Splay
A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval. Input The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. Output You need to answer all Q commands in order. One answer in a line. Sample Input 10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 Sample Output 4 55 9 15 Hint
The sums may exceed the range of 32-bit integers.
Source
POJ Monthly--2007.11.25, Yang Yi
|
[Submit] [Go Back] [Status] [Discuss]
树状数组的改段求段操作:
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn=2100100;
int n,q;
long long int b[maxn],c[maxn];
void init()
{
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
}
int lowbit(int x)
{
return x&(-x);
}
void add_b(int p,long long int v)
{
for(int i=p;i;i-=lowbit(i)) b[i]+=v;
}
void add_c(int p,long long int v)
{
for(int i=p;i<maxn;i+=lowbit(i)) c[i]+=p*v;
}
long long int sum_b(int p)
{
long long int ret=0;
for(int i=p;i<maxn;i+=lowbit(i)) ret+=b[i];
return ret;
}
long long int sum_c(int p)
{
long long int ret=0;
for(int i=p;i;i-=lowbit(i)) ret+=c[i];
return ret;
}
void ADD(int L,int R,long long int v)
{
add_b(R,v);
add_c(R,v);
if(L-1)
{
add_b(L-1,-v);
add_c(L-1,-v);
}
}
long long int sUm(int p)
{
if(p==0) return 0;
return sum_b(p)*p+sum_c(p-1);
}
long long int SUM(int L,int R)
{
return sUm(R)-sUm(L-1);
}
int main()
{
while(scanf("%d%d",&n,&q)!=EOF)
{
init();
for(int i=1;i<=n;i++)
{
int v;
scanf("%d",&v);
ADD(i,i,v);
}
while(q--)
{
char str[10];
scanf("%s",str);
if(str[0]=='Q')
{
int l,r;
scanf("%d%d",&l,&r);
printf("%I64d\n",SUM(l,r));
}
else if(str[0]=='C')
{
int l,r;
long long int v;
scanf("%d%d%I64d",&l,&r,&v);
ADD(l,r,v);
}
}
}
return 0;
}
Splay的延时标记:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long int LL;
const int maxn=100100;
const int INF=0x3f3f3f3f;
#define Key_value ch[ch[root][1]][0]
int pre[maxn],ch[maxn][2],key[maxn],size[maxn],a[maxn];
int n,m;
LL add[maxn],sum[maxn];
int root,tot;
/*******************debug*******************/
void Debug(int x)
{
if(x)
{
Debug(ch[x][0]);
cout<<"节点:"<<x<<" Key: "<<key[x]<<" left_son: "<<ch[x][0]<<" right_son: "<<ch[x][1]
<<" size: "<<x<<" Sum: "<<sum[x]<<endl;
Debug(ch[x][1]);
}
}
/*******************************************/
void NewNode(int& r,int father,int k)
{
r=++tot;
pre[r]=father;
ch[r][0]=ch[r][1]=add[r]=0;
sum[r]=key[r]=k;
size[r]=1;
}
void Update_Add(int x,int v)
{
if(x==0) return ;
sum[x]+=(LL)size[x]*v;
key[x]+=v;
add[x]+=v;
}
void Push_Up(int x)
{
sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+key[x];
size[x]=size[ch[x][0]]+size[ch[x][1]]+1;
}
void Push_Down(int x)
{
if(add[x])
{
Update_Add(ch[x][0],add[x]);
Update_Add(ch[x][1],add[x]);
add[x]=0;
}
}
void Build(int &x,int l,int r,int father)
{
if(l>r) return ;
int m=(l+r)>>1;
NewNode(x,father,a[m]);
Build(ch[x][0],l,m-1,x);
Build(ch[x][1],m+1,r,x);
Push_Up(x);
}
void Init()
{
tot=root=0;
ch[root][0]=ch[root][1]=pre[root]=key[root]=sum[root]=add[root]=size[root]=0;
NewNode(root,0,-INF);
NewNode(ch[root][1],root,INF);
for(int i=1;i<=n;i++) scanf("%d",a+i);
Build(Key_value,1,n,ch[root][1]);
Push_Up(ch[root][1]);
Push_Up(root);
}
void Rotate(int x,int kind)
{
int y=pre[x];
Push_Down(y);
Push_Down(x);
ch[y][!kind]=ch[x][kind];
pre[ch[x][kind]]=y;
if(pre[y]) ch[pre[y]][ch[pre[y]][1]==y]=x;
pre[x]=pre[y];
ch[x][kind]=y;
pre[y]=x;
Push_Up(y);
}
void Splay(int r,int goal)
{
Push_Down(r);
while(pre[r]!=goal)
{
if(pre[pre[r]]==goal)
{
Push_Down(pre[r]);
Push_Down(r);
Rotate(r,ch[pre[r]][0]==r);
}
else
{
Push_Down(pre[pre[r]]);
Push_Down(pre[r]);
Push_Down(r);
int y=pre[r];
int kind=ch[pre[y]][0]==y;
if(ch[y][kind]==r) Rotate(r,!kind);
else Rotate(y,kind);
Rotate(r,kind);
}
}
Push_Up(r);
if(goal==0) root=r;
}
int Get_Kth(int r,int x)
{
Push_Down(r);
int t=size[ch[r][0]]+1;
if(t==x) return r;
else if(t>x) return Get_Kth(ch[r][0],x);
else return Get_Kth(ch[r][1],x-t);
}
void ADD(int l,int r,int v)
{
Splay(Get_Kth(root,l),0);
Splay(Get_Kth(root,r+2),root);
Update_Add(Key_value,v);
Push_Up(ch[root][1]);
Push_Up(root);
}
LL Query(int l,int r)
{
Splay(Get_Kth(root,l),0);
Splay(Get_Kth(root,r+2),root);
return sum[Key_value];
}
int main()
{
while(scanf("%d%d",&n,&m)!=EOF)
{
Init();
char op[20];
while(m--)
{
scanf("%s",op);
int a,b,c;
if(op[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%I64d\n",Query(a,b));
}
else if(op[0]=='C')
{
scanf("%d%d%d",&a,&b,&c);
ADD(a,b,c);
}
}
}
return 0;
}