最近几天系统的做了一下树状数组的各类题型,感觉树状数组真乃神器呀,编程复杂度低,同时功能强大,一维和二,三维的基本上共通。
首先复习一下:树状数组的几个基本操作。
在我的理解中树状数组可以分为两类,插段问点和插点问段,分别对应的是向上更新,向下统计和向下更新,向上统计(一定要真正理解这句话)。
1,lowbit,这就不多说了,精华之一。2,修改操作,对应于某个点的改变,同时被该店所管辖的点也要一起改变。3.统计sum,调用一次sum(a),就意味着对a之前的所有的点都进行了改变。
//注意。在插段问点和插点问段中的求和操作与修改操作是相反的。
int lowbit(int i){
int ans=i&(-i);
return ans;
}
//插点问段
void modify(int k,int d){
while(k<=N){
c[k]+=d;
k+=lowbit(k);
}
}
int sum(int n){
int result=0;
while(n>0){
result+=c[n];
n-=lowbit(n);
}
return result;
}
//插段问点
void modify1(int k,int num){
while(k>0){
c[k]+=num;
k-=lowbit(k);
}
}
int sum1(int n){//用于统计某个点的出现的次数
int s=0;
while(n<=N){
s+=c[n];
n+=lowbit(n);
}
return s;
}
2.二维树状数组模板
static void inc(int i, int j, int t) {
int temj;
for (; i <= Max; i += lowbit(i)) {
for (temj = j; temj <= Max; temj += lowbit(temj)) {
arr[i][temj] += t;
}
}
}
static int getSum(int i, int j) {
int temj, sum = 0;
for (; i > 0; i -= lowbit(i)) {
for (temj = j; temj > 0; temj -= lowbit(temj))
sum += arr[i][temj];
}
return sum;
}
}
在这里介绍两道中等难度的题目:
poj 3321 Apple Tree
这题需要把一个树形结构变换为线性结构,然后使用树状数组动态求和。变换方法为DFS一次这棵树,记录下每个节点第一次访问和最后一次访问时的顺序编号,这时,在某节点第一次访问和最后一次访问编号之间的访问编号,必定为该节点的子节点,按照访问编号建立树状数组,当改变某一节点苹果时,只需按照该节点第一次访问的编号在树状数组中修改值,查询时统计某节点在第一次访问和最后一次访问编号之间的和。
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.InputMismatchException;
public class E {
class FastIO {
int nextInt() throws IOException {
return Integer.valueOf(next());
}
long nextLong() throws IOException {
return Long.valueOf(next());
}
double nextDouble() throws IOException{
return Double.valueOf(next());
}
String next() throws IOException {
StringBuilder sb = new StringBuilder();
char c = skipChar();
while (Character.isWhitespace(c))
c = skipChar();
while (!Character.isWhitespace(c)) {
sb.append(c);
c = getChar();
}
return sb.toString();
}
char skipChar() throws IOException {
int tmp = bfr.read();
if (tmp == -1)
throw new InputMismatchException();
return (char) tmp;
}
char getChar() throws IOException {
return (char) bfr.read();
}
void end() {
out.flush();
out.close();
}
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
}
static int maxn=100010;
static int c[]=new int[maxn];
static int start[]=new int[maxn];
static int end[]=new int[maxn];
static int flag[]=new int[maxn];
static int data[]=new int[maxn];
static int head[]=new int[maxn];
static int edgenum;
static int idx;
class Node{
int v,next;
}
Node eg[]=new Node[maxn*2];
static void init()
{
edgenum=0;
idx=0;
for(int i=0;i<maxn;i++)
{
c[i]=0;
flag[i]=0;
start[i]=0;
end[i]=0;
head[i]=-1;
data[i]=1;
}
}
void addedge(int u,int v)
{
eg[edgenum]=new Node();
eg[edgenum].v=v;
eg[edgenum].next=head[u];
head[u]=edgenum++;
}
void dfs(int x)
{
int i;
flag[x]=1;
idx++;
start[x]=idx;
for( i=head[x];i!=-1;i=eg[i].next)
{
if(flag[eg[i].v]==0)
dfs(eg[i].v);
}
end[x]=idx;
}
static int lowbit(int x)
{
return x&(-x);
}
static void modify(int x,int add)
{
for(int i=x;i<maxn;i+=lowbit(i))
{
c[i]+=add;
}
}
static int sum(int a)
{
int sum=0;
for(int i=a;i>0;i-=lowbit(i))
sum+=c[i];
return sum;
}
void run() throws IOException
{
FastIO in=new FastIO();
int num=in.nextInt();
init();
for(int i=1;i<=num;i++)
modify(i,1);
for(int i=1;i<num;i++)
{
int u=in.nextInt();
int v=in.nextInt();
addedge(u,v);
addedge(v,u);
}
dfs(1);
int qnum=in.nextInt();
while(qnum--!=0)
{
String inc=in.next();
int ds=in.nextInt();
if(inc.equals("Q"))
{
int ans=sum(end[ds])-sum(start[ds]-1);
System.out.println(ans);
}else
{
if(data[ds]==1)
{
modify(start[ds],-1);
}else if(data[ds]==0)
{
modify(start[ds],1);
}
data[ds]^=1;
}
}
}
public static void main(String[] args) throws IOException {
new E().run();
}
}
POJ 2155
插段问点的典型问题:
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.InputMismatchException;
public class B {
class FastIO {
int nextInt() throws IOException {
return Integer.valueOf(next());
}
long nextLong() throws IOException {
return Long.valueOf(next());
}
double nextDouble() throws IOException{
return Double.valueOf(next());
}
String next() throws IOException {
StringBuilder sb = new StringBuilder();
char c = skipChar();
while (Character.isWhitespace(c))
c = skipChar();
while (!Character.isWhitespace(c)) {
sb.append(c);
c = getChar();
}
return sb.toString();
}
char skipChar() throws IOException {
int tmp = bfr.read();
if (tmp == -1)
throw new InputMismatchException();
return (char) tmp;
}
char getChar() throws IOException {
return (char) bfr.read();
}
void end() {
out.flush();
out.close();
}
BufferedReader bfr = new BufferedReader(new InputStreamReader(System.in));
PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));
}
static int maxn=1010;
static int cc[][]=new int[maxn][maxn];
//插段问点
static void init()
{
for(int i=0;i<maxn;i++)
for(int j=0;j<maxn;j++)
cc[i][j]=0;
}
static int lowbit(int x)
{
return x&(-x);
}
static void modify(int a,int b,int add)
{
int i,temj;
for(i=a;i>0;i-=lowbit(i))
{
for(temj=b;temj>0;temj-=lowbit(temj))
cc[i][temj]+=add;
}
}
static int sum(int a,int b)
{
int sum=0,temj;
for(int i=a;i<maxn;i+=lowbit(i))
{
for(temj=b;temj<maxn;temj+=lowbit(temj))
sum+=cc[i][temj];
}
return sum;
}
void run() throws IOException
{
FastIO in=new FastIO();
int num=in.nextInt();
while(num--!=0)
{
init();
int N=in.nextInt();
int qnum=in.nextInt();
for(int i=1;i<=qnum;i++)
{
String inc=in.next();
if(inc.equals("C"))
{
int x1=in.nextInt()+1;
int y1=in.nextInt()+1;
int x2=in.nextInt()+1;
int y2=in.nextInt()+1;
modify(x2,y2,1);
modify(x1-1,y1-1,1);
modify(x2,y1-1,-1);
modify(x1-1,y2,-1);
}else if(inc.equals("Q"))
{
int a=in.nextInt()+1;
int b=in.nextInt()+1;
System.out.println(sum(a,b)%2);
}
}
System.out.println();
}
}
public static void main(String[] args) throws IOException {
new B().run();
}
}