操作序列
时间限制(普通/Java):1000MS/3000MS 运行内存限制:65536KByte
总提交:142 测试通过:23
总提交:142 测试通过:23
描述
给出一初始序列a1, a2,...,an,下面有m个操作(x, l, r) : 对于a[l], a[l+1],...,a[r]都加上x.
输出m个操作结束后的序列.
输入
第一行两个整数n,m(0 <= n,m <= 100000),n表序列{A}的长度, m表操作的个数。
第二行有n 个整数ai(-10000 <= ai <= 10000)。
下面m行,每一行表示一个操作,一个操作表示为3个整数x, l, r(1 <= l <= r <= n, |x|<=1000)。
输出
输出结果序列。
样例输入
5 3
1 2 3 -4 5
2 1 1
-3 3 5
0 1 5
样例输出
3 2 0 -7 2
分析:
典型的线段树问题,由于线段树是完全二叉树,用数组记录即可.
每回操作值都先存入在最大的对应线段上,查询时再统一计算一遍.
插入的时间复杂度为O(logN),查询为O(N *logN);
AC代码如下:
#include<iostream>
using namespace std;
#define maxn 100001
int g_count;int n;
struct node
{
int left;
int right;
int count;
};
struct node A[maxn*4];
void buildtree(struct node *A,int index,int left,int right)
{
A[index].left=left;
A[index].right=right;
A[index].count=0;
if (left==right)
{
return;
}
int mid=(left+right)>>1;
buildtree(A,(index<<1)+1,left,mid);
buildtree(A,(index<<1)+2,mid+1,right);
return;
}
void insert(struct node *A,int index,int start,int end,int key)
{
if (A[index].left==start&&A[index].right==end)
{
A[index].count+=key;
return;
}
int mid=(A[index].left+A[index].right)>>1;
if (end<=mid)
{
insert(A,(index<<1)+1,start,end,key);
}
else
if (start>mid)
{
insert(A,(index<<1)+2,start,end,key);
}
else
{
insert(A,(index<<1)+1,start,mid,key);
insert(A,(index<<1)+2,mid+1,end,key);
}
return;
}
void query(struct node *A,int index,int sum)
{
if (A[index].left==A[index].right)
{
g_count++;
A[index].count+=sum;
if(g_count!=n)
cout<<A[index].count<<' ';
else
cout<<A[index].count<<endl;
return;
}
A[index].count+=sum;
query(A,(index<<1)+1,A[index].count);
query(A,(index<<1)+2,A[index].count);
return ;
}
int main()
{
//freopen("aa.txt","r",stdin);
int m,start,end,key,a;
scanf("%d%d",&n,&m);
buildtree(A,0,1,n);
for (int i=0;i<n;i++)
{
scanf("%d",&a);
insert(A,0,i+1,i+1,a);
}
for (int j=0;j<m;j++)
{
scanf("%d%d%d",&key,&start,&end);
insert(A,0,start,end,key);
}
g_count=0;
query(A,0,0);
return 0;
}