SW练习_POJ2481_COW_indextree

参照:https://www.iteye.com/blog/128kj-1744222

别人的分析记录:

分析: 
  建一个全0的树状数组,然后将牛一个一个插入树状数组,当然必须先对e按照降序排列,每加入一只牛,当前已经加入树状数组的牛的s如果比这只牛小,那么那些牛就更强壮,所以这是在树状数组里的求和问题,只要求出在插入s之前已插入了多少头牛(求和)。另外,由于排序后,顺序和开始给出数据时的顺序不同,所以需要记录一下开始给出数据时的顺序。

先mark下代码 

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++) {  
           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();  
    }  
  }  
} 

 

这个是自己写的

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();  
    }  
  }  
}  

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值