前置细节
- ,得到转二进制后,从右往左数第一个1与之前所有的0构成数
- 树状数组最终形成如上图结构
- 维护的是的信息
- ,如
- 即到上层,包含当前区间的大区间
- ,如
- 即到同一层的前一个,与当前区间无关的另一同等大小的区间
- 的信息是由整合的
- 如维护区间最大值,
- 用于解决将值变小且该值为区间最大值,或将值变大且该值为区间最小值
- 区间和不受影响原因求区间和不用管区间中某一点具体是多少
维护区间和
单点修改
void update(int x,int k) {for(int i=x;i<=size;i=lowbit(i)) {tr[i]+=k;}}
区间修改
- 此时树状数组中维护的是差分数组
单点查询
- 若维护的不是差分数组,直接输出
- 若维护的是差分数组,则,为初值
int query(int x){int res=0;for(int i=x;i>=0;i-=lowbit(i)){res+=t[i];}return res; }
区间查询
- 若维护的不是差分数组 等于前缀和,
- 若维护的是差分数组,则
维护极值
以最大值为例
单点修改
void update(int x,int k) {tr[x]=k;for(int i=x;i<=size;i+=lowbit(i)) {//往上层接着更新int lw=lowbit(i);for(int j=1;j<lw;j<<=1) {tr[i]=Math.max(tr[i], tr[i-j]);//tr[8]=max tr[7],tr[6],tr[4],a[8]//7=8-1.6=8-(10),4=8-(100)}}}
区间查询
int query(int l,int r) {//tr[i]=max [i-lowbit(i)+1,i]//if l<=i-lowbit(i)+1 直接用tr[i]//否则,只能用a[i],剩下递归l,i-1if(l>r)return 0;else if(l==r)return a[l];else if(l<=r-lowbit(r)+1)//包含[l,r]=[r-lowbit(r)+1,r]=tr[r]return Math.max(query(l, r-lowbit(r)),tr[r]);else return Math.max(query(l, r-1), a[r]);}
例:Atcoder Beginner Contest 339 E
题目大意
- 给定一个长度为的序列a,
- 找到a的最长子序列,使得子序列中相邻两值的绝对差不超过
解题思路
- 定义表示以点为起点的最长子序列长度
- 从号开始处理到号,
- 直接暴力过不去
- 考虑用树状数组维护区间最值
- 将看作数组空间,查询区间即为
- 定义为以值为起点的最长子序列长度
- 每处理完一个,则添入树状数组中,保证处理当前第个点,只有的结果在数组里
import java.io.*;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.BitSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.StringTokenizer;
import java.util.Vector;public class Main{static int[] a;static int[] f;//对应长度staticclass BIT{int size;int[] tr;public BIT(int n) {size=n;tr=new int[n+1];}int lowbit(int x) {return x&(-x);}void update(int x,int k) {//可能将当前区间最大值对应的点的值改小tr[x]=f[x]=k;for(int i=x;i<=size;i+=lowbit(i)) {int lw=lowbit(i);for(int j=1;j<lw;j<<=1) {tr[i]=Math.max(tr[i], tr[i-j]);//tr[8]=max tr[7],tr[6],tr[4],a[8]//7=8-1.6=8-(10),4=8-(100)}}}int query(int l,int r) {//tr[i]=max [i-lowbit(i)+1,i]//if l<=i-lowbit(i)+1 直接用tr[i]//否则,只能用a[i],剩下递归l,r-1if(l>r)return 0;else if(l==r)return f[l];else if(l<=r-lowbit(r)+1)return Math.max(query(l, r-lowbit(r)),tr[r]);else return Math.max(query(l, r-1), f[r]);}}public static void main(String[] args) throws IOException{AReader input=new AReader();PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));int n=input.nextInt();int D=input.nextInt();a=new int[n+1];for(int i=0;i<n;++i) {a[i]=input.nextInt();}BIT T=new BIT(500010);f=new int[500010];f[a[n-1]]=1;T.update(a[n-1], 1);for(int i=n-2;i>=0;--i) {int l=a[i]-D<0?0:a[i]-D;int r=a[i]+D>500000?500000:a[i]+D;int t=T.query(l, r)+1;f[a[i]]=t;T.update(a[i], t);}int mx=T.query(0, 500001);out.print(mx);out.flush();out.close();}staticclass AReader{BufferedReader bf;StringTokenizer st;BufferedWriter bw;public AReader(){bf=new BufferedReader(new InputStreamReader(System.in));st=new StringTokenizer("");bw=new BufferedWriter(new OutputStreamWriter(System.out));}public String nextLine() throws IOException{return bf.readLine();}public String next() throws IOException{while(!st.hasMoreTokens()){st=new StringTokenizer(bf.readLine());}return st.nextToken();}public char nextChar() throws IOException{//确定下一个token只有一个字符的时候再用return next().charAt(0);}public int nextInt() throws IOException{return Integer.parseInt(next());}public long nextLong() throws IOException{return Long.parseLong(next());}public double nextDouble() throws IOException{return Double.parseDouble(next());}public float nextFloat() throws IOException{return Float.parseFloat(next());}public byte nextByte() throws IOException{return Byte.parseByte(next());}public short nextShort() throws IOException{return Short.parseShort(next());}public BigInteger nextBigInteger() throws IOException{return new BigInteger(next());}public void println() throws IOException {bw.newLine();}public void println(int[] arr) throws IOException{for (int value : arr) {bw.write(value + " ");}println();}public void println(int l, int r, int[] arr) throws IOException{for (int i = l; i <= r; i ++) {bw.write(arr[i] + " ");}println();}public void println(int a) throws IOException{bw.write(String.valueOf(a));bw.newLine();}public void print(int a) throws IOException{bw.write(String.valueOf(a));}public void println(String a) throws IOException{bw.write(a);bw.newLine();}public void print(String a) throws IOException{bw.write(a);}public void println(long a) throws IOException{bw.write(String.valueOf(a));bw.newLine();}public void print(long a) throws IOException{bw.write(String.valueOf(a));}public void println(double a) throws IOException{bw.write(String.valueOf(a));bw.newLine();}public void print(double a) throws IOException{bw.write(String.valueOf(a));}public void print(char a) throws IOException{bw.write(String.valueOf(a));}public void println(char a) throws IOException{bw.write(String.valueOf(a));bw.newLine();}}
}
感谢这位大佬的博文启发https://blog.csdn.net/TheWayForDream/article/details/118436732