树链相关问题

轻重链剖分求LCA

  • 轻重链剖分,就是将一棵树划分为多个互不相交的链
  • 两遍dfs,复杂度O(n)
  • dfs1: 维护出该节点的直接父亲,在通过其儿子节点中重量最大的(即以其为根的子树大小最大)作为重儿子,也就是该点所在树链的直接儿子,同时维护深度
  • dfs2: 维护每条链的链头,用于处理不在同一条链上的两点求LCA,实现直接跳过一条链
  • 若两点在一条链上,则输出深度较低的点
  • 若两点不在一条链上,则两点中链头深度较大往上跳,直到两个跳到同一条链上
  • 复杂度O(logn)

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.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;










//implements Runnable
public class Main implements Runnable{//利用修改线程,避免栈溢出
	static long md=(long)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	static int N=500000;
	static
	class Edge{
		int fr,to,nxt;
		long val;
		public Edge(int u,int v,long w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static int[] fa=new int[N+1];//该点在链上的直接父亲
	static int[] son=new int[N+1];//该点在链上的直接儿子(重儿子)
	static int[] siz=new int[N+1];//以该点为根的子树大小
	static int[] dep=new int[N+1];//深度
	static int[] top=new int[N+1];//该点所在链的链头
	static
	class Tp{
		Edge[] e;
		int[] head;
		int cnt;
		public Tp() {
			e=new Edge[N*2+1];
			head=new int[N+1];
			cnt=0;
		}
		void addEdge(int fr,int to,long val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		void dfs1(int x) {
			siz[x]=1;
			dep[x]=dep[fa[x]]+1;
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				long w=e[i].val;
				if(v==fa[x])continue;
				fa[v]=x;
				dfs1(v);
				siz[x]+=siz[v];
				if(son[x]==0||siz[son[x]]<siz[v]) 
					son[x]=v;
				
			}
		}
		void dfs2(int x,int tp) {
			top[x]=tp;
			if(son[x]!=0)dfs2(son[x], tp);
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				if(v==fa[x]||v==son[x])continue;
				dfs2(v, v);
			}
		}
		int LCA(int x,int y) {
			while(top[x]!=top[y]) {//直到跳到一条链上
				if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
				else y=fa[top[y]];
			}
			if(dep[x]<dep[y])return x;
			else return y;
		}
	}
	static Tp rel=new Tp();
	
	static void solve() throws Exception{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));	
	    int n=input.nextInt();
	    int m=input.nextInt();
	    int s=input.nextInt();
	    
	    for(int i=1;i<n;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	rel.addEdge(u, v, 0);
	    	rel.addEdge(v, u, 0);
	    }
	    rel.dfs1(s);
	    rel.dfs2(s, s);
	    while(m>0) {
	    	int x=input.nextInt();
	    	int y=input.nextInt();
	    	out.println(rel.LCA(x, y));
	    	
	    	m--;
	    }
 	    out.flush();
	    out.close();
	}
//	public static void main(String[] args) throws Exception{
//本地调试用这个main,因为改线程后不会报错,会直接停止
//		solve();
//	}
	public static final void main(String[] args) throws Exception {
//本地调试将这个和implements Runnable去掉
		  new Thread(null, new Main(), "线程名字", 1 << 27).start();
	}
		@Override
		public void run() {
			try {
				//原本main函数的内容
				solve();

			} catch (Exception e) {
			}
		}
		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();
		    }
		}
	}

		

	

虚树

  • 通过关键点建树,删去关键点影响不到的点,减少树形Dp遍历点的个数
  • 单调栈维护
  • 实际单调栈中维护了一条树链
  • 根先入栈,然后关键点按照dfs序依次入栈
  • 设当前加入的关键点为u,当前栈顶为v,求其p=LCA(u,v)
  • p=v,则u在单调栈维护的树链上,直接入栈
  • p\neq v,则弹出栈顶,并将v与新栈顶连边,然后接着弹栈顶
  • 若当前栈顶的dfs序小于pdfs序,则说明栈中没有p,则将p入栈,弹出的栈顶与其连边
  • 然后将u入栈
  • 最后,再将单调栈中维护的树链,进行连边(依次弹出,并对新栈顶连边)
  • 至此,虚树建立完毕,然后在虚树上跑树形DP
  • 注意,只用在虚树上对该点进行完Dp后,head[x]=0,key[x]=false,实现清空

例题:

消耗战

  Here

解题思路
  • 先得出树形Dp
  • minv[i],表示不能到i最少需要的代价
  • 若当前点是关键点,则只能选择minv,使1不能到达
  • 若不是,则还可以选择1可以到达该点,然后在后续不能到达关键点的代价,取最小的
  • 发现查询很多次,若直接跑则为O(nm)maybe?
  • 然后发现,总共回访问到的点数\sum k\leq 5e5
  • 考虑对于每次询问建立虚树,不相干点不访问
  • 注意虚树要开2倍空间
  • 边值1e5,最终结果回爆int

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.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;










//implements Runnable
public class Main implements Runnable{
	static long md=(long)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	static int N=500000;
	static
	class Edge{
		int fr,to,nxt;
		long val;
		public Edge(int u,int v,long w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static long[] minv=new long[N+1];
	static int[] dfn=new int[N+1];
	static int dfn_tim=0;
    static int[] fa=new int[N+1];
	static int[] son=new int[N+1];
	static int[] siz=new int[N+1];
	static int[] dep=new int[N+1];
	static int[] top=new int[N+1];
	static
	class Tp{
		Edge[] e;
		int[] head;
		int cnt;
		public Tp() {
			e=new Edge[N*2+1];
			head=new int[N+1];
			cnt=0;
		}
		void addEdge(int fr,int to,long val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		void dfs1(int x) {
			siz[x]=1;
			dep[x]=dep[fa[x]]+1;
			dfn_tim++;
			dfn[x]=dfn_tim;
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				long w=e[i].val;
				if(v==fa[x])continue;
				fa[v]=x;
				minv[v]=Math.min(minv[x], w);
				dfs1(v);
				siz[x]+=siz[v];
				if(son[x]==0||siz[son[x]]<siz[v]) 
					son[x]=v;
				
			}
		}
		void dfs2(int x,int tp) {
			top[x]=tp;
			if(son[x]!=0)dfs2(son[x], tp);
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				if(v==fa[x]||v==son[x])continue;
				dfs2(v, v);
			}
		}
		int LCA(int x,int y) {
			while(top[x]!=top[y]) {
				if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
				else y=fa[top[y]];
			}
			if(dep[x]<dep[y])return x;
			else return y;
		}
	}
	static Tp rel=new Tp();
	static
	class Node{
		int x;
		int y;
		public Node(int u,int v) {
			x=u;
			y=v;
		}
	}
	static int k=0;
	static Node[] h=new Node[N+1];
	static boolean[] isk=new boolean[N+1];
	static
	class Tv{
		Edge[] e;
		int[] head;
		int cnt;
		public Tv() {
			e=new Edge[N*2+1];
			head=new int[N+1];
			cnt=0;
		}
		void addEdge(int fr,int to) {
			cnt++;
			e[cnt]=new Edge(fr, to, 0);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		void Make_vi() {
			Stack<Integer> st=new Stack<Integer>();
			Arrays.sort(h,1,k+1,(o1,o2)->{
				return o1.y-o2.y;
			});
			st.add(1);
			for(int i=1;i<=k;++i) {
				int u=h[i].x;
				int p=rel.LCA(st.peek(), u);
				while(st.peek()!=p) {
					int pre=st.peek();st.pop();
					if(dfn[st.peek()]<dfn[p]){
						st.add(p);
					}
					addEdge(st.peek(), pre);
				}
				st.add(u);
			}
			while(st.peek()!=1) {
				int pre=st.peek();
				st.pop();
				addEdge(st.peek(), pre);
			}
		}
		long Tree_Dp(int x) {
			long sum=0;
			long res=0;
			for(int i=head[x];i>0;i=e[i].nxt) {
				sum+=Tree_Dp(e[i].to);
			}
			if(isk[x])res=minv[x];
			else res=Math.min(minv[x], sum);
			isk[x]=false;
			head[x]=0;
			return res;
		}
	}
	static Tv vir=new Tv();
	static void solve() throws Exception{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));	
	    int n=input.nextInt();
	    for(int i=1;i<n;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	long w=input.nextLong();
	    	rel.addEdge(u, v, w);
	    	rel.addEdge(v, u, w);
	    }
	    minv[1]=Linf;
	    rel.dfs1(1);
	    rel.dfs2(1,1);
	    int m=input.nextInt();
	    while(m>0) {
	    	k=input.nextInt();
	    	for(int i=1;i<=k;++i) {
	    		int x=input.nextInt();
	    		isk[x]=true;
	    		if(h[i]==null)h[i]=new Node(x, dfn[x]);
	    		else {
	    			h[i].x=x;
	    			h[i].y=dfn[x];
	    		}
	    	}
	    	vir.Make_vi();
	    	out.println(vir.Tree_Dp(1));
	    	
	    	m--;
	    }
	    
 	    out.flush();
	    out.close();
	}
//	public static void main(String[] args) throws Exception{
//		solve();
//	}
	public static final void main(String[] args) throws Exception {
		  new Thread(null, new Main(), "线程名字", 1 << 27).start();
	}
		@Override
		public void run() {
			try {
				//原本main函数的内容
				solve();

			} catch (Exception e) {
			}
		}
		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();
		    }
		}
	}

		

	

大工程

Here


 

解题思路
  • 先考虑树形Dp
  • 对于每个点得出,以该点为根的子树中,任意两个关键点的最长链和最短链
  • 对于每个点维护离其子树中关键点最远fmx和最近的距离gmi
  • 设当前点为u,依次访问其儿子,后面的向前连,一定不会漏
  • 对于每个儿子v考虑,以v为根的子树中有无关键点
  • 若有,则可以通过u点去访问u子树中的其他关键点(包括u自身),更新最长链和最短链
  • 这样相连的关键点一定是最短路径(两点通过其lca相连)
  • 发现\sum kn同阶,则考虑建虚树,同上题用单调栈
package Tx;
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.Map;
import java.util.Objects;
import java.util.PriorityQueue;
import java.util.Queue;
import java.util.Random;
import java.util.Scanner;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;










//implements Runnable
public class Tx2{
	static long md=(long)998244353;
	static long Linf=Long.MAX_VALUE/2;
	static int inf=Integer.MAX_VALUE/2;
	static int N=500000;
	static
	class Edge{
		int fr,to,nxt;
		long val;
		public Edge(int u,int v,long w) {
			fr=u;
			to=v;
			val=w;
		}
	}
	static int[] fa=new int[N+1];
	static int[] son=new int[N+1];
	static int[] siz=new int[N+1];
	static int[] dep=new int[N+1];
	static int[] top=new int[N+1];
	static int[] dfn=new int[N+1];
	static int dfn_tim=0;
	static
	class Tp{
		Edge[] e;
		int[] head;
		int cnt;
		public Tp() {
			e=new Edge[N*2+1];
			head=new int[N+1];
			cnt=0;
		}
		void addEdge(int fr,int to,long val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		void dfs1(int x) {
			siz[x]=1;
			dep[x]=dep[fa[x]]+1;
			dfn_tim++;
			dfn[x]=dfn_tim;
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				long w=e[i].val;
				if(v==fa[x])continue;
				fa[v]=x;
				dfs1(v);
				siz[x]+=siz[v];
				if(son[x]==0||siz[son[x]]<siz[v]) 
					son[x]=v;
				
			}
		}
		void dfs2(int x,int tp) {
			top[x]=tp;
			if(son[x]!=0)dfs2(son[x], tp);
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				if(v==fa[x]||v==son[x])continue;
				dfs2(v, v);
			}
		}
		int LCA(int x,int y) {
			while(top[x]!=top[y]) {
				if(dep[top[x]]>dep[top[y]])x=fa[top[x]];
				else y=fa[top[y]];
			}
			if(dep[x]<dep[y])return x;
			else return y;
		}
	}
	static Tp rel=new Tp();
	static long[] fmx=new long[N+1];
	static long[] gmi=new long[N+1];
	static int[] sz=new int[N+1];
	static long sum=0;
	static long mi=inf;
	static long mx=-inf;
	static
	class Node{
		int x;
		int y;
		public Node(int u,int v) {
			x=u;
			y=v;
		}
	}
	static int k=0;
	static Node[] h=new Node[N+1];
	static boolean[] isk=new boolean[N+1];
	static 
	class Tv{
		Edge[] e;
		int[] head;
		int cnt;
		public Tv() {
			e=new Edge[N*2+1];
			head=new int[N+1];
			cnt=0;
		}
		void addEdge(int fr,int to,long val) {
			cnt++;
			e[cnt]=new Edge(fr, to, val);
			e[cnt].nxt=head[fr];
			head[fr]=cnt;
		}
		void Make_Vir() {
			Stack<Integer> st=new Stack<Integer>();
			Arrays.sort(h,1,k+1,(o1,o2)->{
				return o1.y-o2.y;
			});
			st.add(1);
			for(int i=1;i<=k;++i) {
				int u=h[i].x;
				int p=rel.LCA(u, st.peek());
				while(p!=st.peek()) {
					int pre=st.peek();st.pop();
					if(dfn[st.peek()]<dfn[p]) {
						st.add(p);
					}
					addEdge(st.peek(), pre, dep[pre]-dep[st.peek()]);
				}
				st.add(u);
			}
			while(st.peek()!=1) {
				int pre=st.peek();st.pop();
				addEdge(st.peek(), pre, dep[pre]-dep[st.peek()]);
			}
		}
		void Tree_dp(int x) {
			if(isk[x]) {
				sz[x]=1;
				fmx[x]=0;
				gmi[x]=0;
			}else {
				sz[x]=0;
				fmx[x]=0;
				gmi[x]=inf;
			}
			for(int i=head[x];i>0;i=e[i].nxt) {
				int v=e[i].to;
				long w=e[i].val;
				Tree_dp(v);
				sum+=w*(k-sz[v])*sz[v];
				
				if(sz[x]>0) {
					mi=Math.min(mi, gmi[x]+w+gmi[v]);
					mx=Math.max(mx, fmx[x]+w+fmx[v]);
				}
				fmx[x]=Math.max(fmx[x], fmx[v]+w);
				gmi[x]=Math.min(gmi[x], gmi[v]+w);
				sz[x]+=sz[v];
			}
			isk[x]=false;
			head[x]=0;
		}
	}
	static Tv vir=new Tv();
	static void solve() throws Exception{
		AReader input=new AReader();
	    PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));	
	    int n=input.nextInt();
	    for(int i=1;i<n;++i) {
	    	int u=input.nextInt();
	    	int v=input.nextInt();
	    	rel.addEdge(u, v, 0);
	    	rel.addEdge(v, u, 1);
	    }
	    rel.dfs1(1);
	    rel.dfs2(1, 1);
	    int m=input.nextInt();
	    while(m>0) {
	    	sum=0;
	    	mx=-inf;
	    	mi=inf;
	    	k=input.nextInt();
	    	
	    	for(int i=1;i<=k;++i) {
	    		int x=input.nextInt();
	    		isk[x]=true;
	    		if(h[i]==null)h[i]=new Node(x, dfn[x]);
	    		else {
	    			h[i].x=x;
	    			h[i].y=dfn[x];
	    		}
	    	}
	    	vir.Make_Vir();
	    	vir.Tree_dp(1);
	    	
	    	out.println(sum+" "+mi+" "+mi);
	    	
	    	m--;
	    }
 	    out.flush();
	    out.close();
	}
	public static void main(String[] args) throws Exception{
		solve();
	}
//	public static final void main(String[] args) throws Exception {
//		  new Thread(null, new Main(), "线程名字", 1 << 27).start();
//	}
//		@Override
//		public void run() {
//			try {
//				//原本main函数的内容
//				solve();
//
//			} catch (Exception e) {
//			}
//		}
		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();
		    }
		}
	}

		

	

 

  • 17
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值