倒计时1

一、树状数组练习题
有n头牛(编号为1~n),每一头牛都有一个吃草区间[S, E],如果对于牛i和牛j来说,它们的吃草区间满足下面的条件则证明牛i比牛j强壮:Si <= Sj and Ej <= Ei and Ei - Si > Ej - Sj。现在已知每一头牛的吃草区间,要求输出每头牛有几头牛比其强壮。
其中:1 <= N <= 100000, 0 <= S < E <= 100000

样例:

Sample Input

3 (3头牛)
1 2 牛的[s,e]值
0 3
3 4
0

Sample Output

1 0 0 (比第一头牛强的有一头,比第二头牛强的没有,比第三头牛强的没有)

import java.io.StreamTokenizer;     
import java.io.BufferedReader;     
import java.io.InputStreamReader;     
import java.io.PrintWriter;     
import java.io.OutputStreamWriter;     
import java.io.IOException;     
import java.util.Arrays;  
  
   class TNode implements Comparable{//表示一头牛  
    int s;//牛吃草的左端点  
    int e;//右端点  
    int label;//牛的序号  
    public int compareTo(Object o) {    
       int v=((TNode)o).e;  
       if(this.e!=v) //按右端点降序排列  
         return v-this.e;     
       return this.s-((TNode)o).s;//右端点相等,按左端点升序排序  
    }  
  
    public String toString(){  
        return ("["+s+","+e+"]");  
    }  
  }  
  
 public class Main{//  
   static  int N=100015;  
   TNode[] cow;  
   int cal[];//树状数组  
   int res[];//res[i]表示比牛i强壮的牛的个数  
   int maxn;//右端点的最大值  
  
  public Main(){  
      
     }  
         
   private int lowbit(int t){//计算cal[t]展开的项数     
   return t&(-t);     
  }     
  
  private int Sum(int k){ //求前k项的和.     
   int sum=0;      
    while(k>0){      
       sum+=cal[k];      
       k=k-lowbit(k);      
    }          
    return sum;      
  }      
  
  private void update(int i,int x){ //增加某个元素的大小,给某个节点 i 加上 x     
      while(i<=maxn){      
        cal[i]=cal[i]+x; //更新父节点  
        i=i+lowbit(i);      
     }      
    }      
  
    
     
  
  public static void  main(String args[]) throws IOException{  
        Main ma=new Main();  
        ma.go();  
   }  
  
    public void go() throws IOException{  
       
      StreamTokenizer st = new StreamTokenizer(new BufferedReader(        
      new InputStreamReader(System.in)));        
      PrintWriter out = new PrintWriter(new OutputStreamWriter(System.out));        
  
      while(true) {  
       st.nextToken();        
      int n= (int) st.nval;    //牛的个数    
      if(n==0) break;  
  
     cow=new TNode[N];  
     cal=new int[N];  
     res=new int[N];  
     for(int i=0;i<N;i++){  
       cow[i]=new TNode();  
      // cal[i]=0;  
      }  
      for(int i=0;i<n;i++) {//读入牛的吃草区间  
            st.nextToken();       
           cow[i].s=(int) st.nval;  
             st.nextToken();       
           cow[i].e=(int) st.nval;  
           cow[i].s++;   
           cow[i].e++;  
           cow[i].label=i;//牛的原始序号  
           if(cow[i].e>maxn) maxn=cow[i].e;//最大右端点  
      }  
         
        Arrays.sort(cow);//排序  
  
     // for(int i=0;i<n;i++)  
       // System.out.println(cow[i]);  
   
      for(int i=0;i<n;i++) {  
           if(i!=0&&cow[i].s==cow[i-1].s&&cow[i].e==cow[i-1].e)//两头牛有相同的吃草区间  
                res[cow[i].label]=res[cow[i-1].label];//它们有相同的答案  
            else res[cow[i].label]=Sum(cow[i].s);//统计比cow[i].label这头牛强的牛的数目  
            update(cow[i].s,1);//更新  
        }  
        System.out.printf("%d",res[0]);  
        for(int i=1;i<n;i++) System.out.printf(" %d",res[i]);  
        System.out.println();  
    }  
  }  
}   

二、祖先问题

package day_6;

import java.util.ArrayList;
import java.util.List;
 
public class Demo1 {
	public static void main(String[] args) {
		test01();
	}
	
	// 形状普通的树
    //             1
    //           /   \
    //         2      3
    //        /         \
    //      4            5
    //     / \        /  |  \
    //    6   7      8   9  10
    public static void test01() {
        TreeNode n1 = new TreeNode(1);
        TreeNode n2 = new TreeNode(2);
        TreeNode n3 = new TreeNode(3);
        TreeNode n4 = new TreeNode(4);
        TreeNode n5 = new TreeNode(5);
        TreeNode n6 = new TreeNode(6);
        TreeNode n7 = new TreeNode(7);
        TreeNode n8 = new TreeNode(8);
        TreeNode n9 = new TreeNode(9);
        TreeNode n10 = new TreeNode(10);
 
        n1.children.add(n2);
        n1.children.add(n3);
 
        n2.children.add(n4);
 
        n4.children.add(n6);
        n4.children.add(n7);
 
        n3.children.add(n5);
 
        n5.children.add(n8);
        n5.children.add(n9);
        n5.children.add(n10);
 
        System.out.println(getLastCommonParent(n1, n9, n10));
    }
 
	/*
	 * 获取两个节点的最低公共祖先
	 */
	public static TreeNode getLastCommonParent(TreeNode root, TreeNode p1, TreeNode p2) {
		//path1和path2分别存储根节点到p1和p2的路径(不包括p1和p2)
		List<TreeNode> path1 = new ArrayList<TreeNode>();
		List<TreeNode> path2 = new ArrayList<TreeNode>();
		List<TreeNode> tmpList = new ArrayList<TreeNode>();
 
		getNodePath(root, p1, tmpList, path1);
		getNodePath(root, p2, tmpList, path2);
		//如果路径不存在,返回空
		if (path1.size() == 0 || path2.size() == 0)
			return null;
 
		return getLastCommonParent(path1, path2);
	}
 
	// 获取根节点到目标节点的路径
	public static void getNodePath(TreeNode root, TreeNode target, List<TreeNode> tmpList, List<TreeNode> path) {
		//鲁棒性
		if (root == null || root == target)
			return;
		tmpList.add(root);
		List<TreeNode> children = root.children;
		for (TreeNode node : children) {
			if (node == target) {
				path.addAll(tmpList);
				break;
			}
			getNodePath(node, target, tmpList, path);
		}
 
		tmpList.remove(tmpList.size() - 1);
	}
	//将问题转化为求链表最后一个共同节点
	private static TreeNode getLastCommonParent(List<TreeNode> p1, List<TreeNode> p2) {
		TreeNode tmpNode = null;
		for (int i = 0; i < p1.size(); i++) {
			if (p1.get(i) != p2.get(i))
				break;
			tmpNode = p1.get(i);
		}
 
		return tmpNode;
	}
 
	// 节点类
	private static class TreeNode {
		int val;
 
		List<TreeNode> children = new ArrayList<TreeNode>();
 
		public TreeNode(int val) {
			this.val = val;
		}
		@Override
		public String toString() {
			return val + "";
		}
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值