思路:修改一个区间的值,然后求单个点的值,树状数组的大水题啊~~~今天刚学这种用法~~十分钟左右就敲完了~以前只会简单的区间求和~今天才学了这种区间更新,单点求值~
其实就是区间求和逆过来做~唔,要注意Presentation Error,好几次之后。。。才发现末尾不能有空格。。。
举例说明吧:
c[1]=a[1];
c[2]=a[1]+a[2];
c[3]=a[3];
c[4]=a[1]+a[2]+a[3]+a[4];
c[5]=a[5];
c[6]=a[5]+a[6];
c[7]=a[7];
c[8]=a[1]+...+a[8];
假如我要更新区间[3,7],每个节点+1,那么我首先更新[1,7],即该区间+1;再更新[1,2],该区间-1。
由于更新时往叶子节点(c[1]节点)拓展的,所以更新[1,7]时:c[7]++,c[6]++,c[4]++。
可以发现,这三个正好包含了a[1]~a[7]一次,相当于a[1]~a[7]都更新一遍
而更新[1,2]时:c[2]--,包含了a[1],a[2]。
那么当我查询某一值a[i],由于是往根节点(c[8])拓展,所以每个包含a[i]的c[j]都会遇到一次,即之前凡是更新过的值我都会加上。
如我想查询a[2],那么a[2]=c[2]+c[4]+c[8]=-1+1+0=0;
查询a[3],那么a[3]=c[3]+c[4]+c[8]=0+1+0=1。
说到这里,大家应该明白了点吧。
AC代码:
import java.util.Scanner;
public class Main
{
static Scanner scan=new Scanner(System.in);
private static int lowbit(int x) {return x&(-x);}
private static void upDate(int[] c,int l,int r,int x)
{
for(int i=r;i>0;i-=lowbit(i))
c[i]+=x;
for(int i=l-1;i>0;i-=lowbit(i))
c[i]-=x;
}
private static int sum(int[] c,int n,int x)
{
int sum=0;
for(int i=x;i<=n;i+=lowbit(i))
sum+=c[i];
return sum;
}
public static void main(String[] args)
{
while(scan.hasNext())
{
int n=scan.nextInt();
if(n==0) break;
int c[]=new int[n+1];
for(int i=1;i<=n;i++)
{
int l=scan.nextInt();
int r=scan.nextInt();
upDate(c,l,r,1);
}
System.out.print(sum(c,n,1));
for(int i=2;i<=n;i++)
System.out.print(" "+sum(c,n,i));
System.out.println();
}
}
}