树状数组相关

前置细节 

  • lowbit(x)=x\&(-x),得到x转二进制后,从右往左数第一个1与之前所有的0构成数
  • 树状数组相关_第1张图片
  • 树状数组最终形成如上图结构
  • t[i]维护的是[i-lowbit(i)+1,i]的信息
  • i+lowbit(x),如4\rightarrow 8=100+100,6\rightarrow 8=110+10,7\rightarrow 8=111+1
  • 即到上层,包含当前区间的大区间
  • i-lowbit(i),如6\rightarrow 4=110-10,5\rightarrow 2=101-1
  • 即到同一层的前一个,与当前区间无关的另一同等大小的区间
  • t[i]的信息是由a[i],t[i-1],t[i-(10) ],\cdots ,t[i-j](j<lowbit(i))整合的
  • 如维护区间最大值,t[8]= max\ a[8],t[7],t[6],t[4]
  • 用于解决将值变小且该值为区间最大值,或将值变大且该值为区间最小值
  • 区间和不受影响原因求区间和不用管区间中某一点具体是多少

维护区间和

单点修改

void update(int x,int k) {
		for(int i=x;i<=size;i=lowbit(i)) {
			tr[i]+=k;
		}
	}

区间修改

  • 此时树状数组中维护的是差分数组 
  • add(l,r,k)\Rightarrow update(l,k),update(r,-k)

单点查询 

  • 若维护的不是差分数组,直接输出t[x]
  • 若维护的是差分数组,则ans=a[x]+query(x)a[x]为初值 
    int query(int x){
        int res=0;
        for(int i=x;i>=0;i-=lowbit(i)){
            res+=t[i];
        }
        return res;
    }

区间查询 

  • 若维护的不是差分数组 query(x)等于前缀和,Sum(l,r)=query(r)-query(l-1)
  • 若维护的是差分数组,则Sum(l,r)=\sum_{i=l}^{r}a[x]+query(x)

维护极值

以最大值为例 

单点修改 

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

区间查询 

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-1
			if(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

题目大意
  • 给定一个长度为n的序列a,1\leq a_i\leq 5*1e5
  • 找到a的最长子序列,使得子序列中相邻两值的绝对差不超过D
解题思路
  • 定义f[i]表示以i点为起点的最长子序列长度
  • n-1号开始处理到0号,f[i]=(Max_{j=i+1}^{n-1} f[j])+1\&\&Math.abs(a[i]-a[j])<=D
  • 直接暴力O(n^2)过不去
  • 考虑用树状数组维护区间最值
  • 0\rightarrow 5*1e5看作数组空间,查询区间即为[max (a[i]-D,0),min(a[i]+D,5*1e5)]
  • f[i]定义为以值i为起点的最长子序列长度
  • 每处理完一个f[i],则添入树状数组中,保证处理当前第k个点,只有k+1\rightarrow n-1的结果在数组里
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;//对应长度
	static
	class 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;jr)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=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();
	}
	static
	class 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();
	    }
	}
}

感谢这位大佬的博文启发icon-default.png?t=N7T8https://blog.csdn.net/TheWayForDream/article/details/118436732

你可能感兴趣的:(算法,java,数据结构)