POJ 3468 A Simple Problem with Integers
题目大意:用n个整数,给指定区间的数,每个数字加上某个数,或者求指定区间的和。
思路如下:线段树成段更新与区间求和的裸题~这题按通常来讲似乎是不会TLE的,但是还是可以用快速io或者lazy思想来加速。lazy就是在给区间[i,j]全体加上一个数时,只更新区间[i,j]及其上的节点,然后在这里做一个标记,当查询有需要调用下面节点的内容时,再把下面原本没有更新的地方更新了。
AC代码:
import java.util.Scanner;
public class Main
{
static int maxn=100000;
static long sum[]=new long[maxn<<2];
static long lazy[]=new long[maxn<<2];
static Scanner scan=new Scanner(System.in);
public static void buildTree(int l, int r, int rt)
{
if(l==r){sum[rt]=scan.nextInt();return;}
int mid=(l+r)>>1;
buildTree(l, mid, rt<<1);
buildTree(mid+1, r, rt<<1|1);
pushUp(rt);
}
public static void upDate(int L, int R, int add, int l, int r, int rt)
{
if(L<=l && r<=R)
{
sum[rt]+=(r-l+1)*add;
lazy[rt]+=add;
return;
}
pushDown(rt, r-l+1);//检查是否需要往下更新,因为下面的两个if需要用到rt的两个子节点的内容
int mid=(l+r)>>1;
if(L<=mid) upDate(L, R, add, l, mid, rt<<1);
if(R>mid) upDate(L, R, add, mid+1, r, rt<<1|1);
pushUp(rt);
}
public static void pushUp(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}
public static void pushDown(int rt, int m)
{
if(lazy[rt]!=0)//此处等于0时即不需要往下更新,无可更新内容
{
sum[rt<<1]+=lazy[rt]*(m-(m>>1));
sum[rt<<1|1]+=lazy[rt]*(m>>1);
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
public static long query(int L, int R, int l, int r, int rt)
{
if(L<=l && r<=R) return sum[rt];
pushDown(rt, r-l+1);//检查是否需要往下更新,因为下面的两个if需要用到rt的两个子节点的内容
int mid=(l+r)>>1;
long sum=0;
if(L<=mid) sum+=query(L, R, l, mid, rt<<1);
if(R>mid) sum+=query(L, R, mid+1, r, rt<<1|1);
return sum;
}
public static void main(String[] args)
{
int n=scan.nextInt();
int m=scan.nextInt();
buildTree(1, n, 1);
while(m-->0)
{
String key=scan.next();
int a=scan.nextInt();
int b=scan.nextInt();
if(key.charAt(0)=='Q')
System.out.println(query(a, b, 1, n, 1));
if(key.charAt(0)=='C')
{
int c=scan.nextInt();
upDate(a, b, c, 1, n, 1);
}
}
}
}