zoukankan      html  css  js  c++  java
  • poj 2481 Cows(数状数组 或 线段树)

    题意:对于两个区间,[si,ei] 和 [sj,ej],若 si <= sj and ei >= ej and ei - si > ej - sj 则说明区间 [si,ei] 比 [sj,ej] 强。对于每个区间,求出比它强的区间的个数。

    解题思路:先将每个区间按 e 降序排列,在按 s 升序排列。则对于每个区间而言,比它强的区间的区间一定位于它的前面。 利用数状数组求每个区间[si,ei]前面 满足条件的区间[sj,ej]个数(条件:ej<=ei),再减去前面的和它相同的区间的个数。 也可以利用线段树,下面附上两种代码

    代码:

    
    数状数组
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    using namespace std;
    
    int n,MAX,c[400010],r[400010],s[400010],e[400010];
    
    int cmp(const int x,const int y){
    	if(e[x] > e[y])
    		return 1;
    	else if( e[x] == e[y] )
    		return s[x] <= s[y];
    	return 0;
    }
    
    int lowbit(int x){
    	return x&(-x);
    }
    
    int sum(int x){
    	int ret  = 0;
    	while( x > 0){
    		ret += c[x];
    		x -= lowbit(x);
    	}
    	return ret;
    }
    
    void add(int x,int d){
    	while(x <= MAX){
    		c[x] += d;
    		x += lowbit(x);
    	}
    }
    
    int main(){
    	int i,j,ans[100010];
    	while(scanf("%d",&n) == 1 && n){
    		MAX  = 0;
    		for(i=0;i<n;i++){
    			scanf("%d%d",&s[i],&e[i]);
    			s[i] ++;
    			e[i] ++;
    			MAX = MAX > s[i] ? MAX : s[i];
    		}
    		for(i=0;i<n;i++)
    			r[i] = i;
    		sort(r,r+n,cmp);
    		memset(c,0,sizeof(c));
    		for(i=0;i<n;i++){
    			int t = r[i];
    			ans[t] = sum(s[t]);
    			add(s[t],1);
    			for(j=i-1;j>=0;j--)
    				if(e[r[j]] == e[t] && s[r[j]] == s[t])
    				   ans[t] --;
    				else
    				    break;	
    		}
    		for(i=0;i<n-1;i++)
    			printf("%d ",ans[i]);
    		printf("%d
    ",ans[n-1]);
    	}
    	return 0;
    }
    
    
    线段树
    
    #include<iostream>
    #include<cstdlib>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    using namespace std;
    
    int n,MAX,r[200010],s[200010],e[200010];
    struct node{
    	int l,r;
    	int value;
    }a[800010];
    
    int cmp(const int x,const int y){
    	if(e[x] > e[y])
    		return 1;
    	else if(e[x] == e[y])
    		return s[x] <= s[y];
    	return 0;
    }
    
    void buildtree(int i,int l,int r){
    	a[i].l = l;
    	a[i].r = r;
    	a[i].value = 0;
    	if( l== r)
    		return ;
    	int mid = (l+r) / 2 ;
    	buildtree(i<<1,l,mid);
    	buildtree((i<<1) + 1,mid+1,r);
    }
    
    int query(int i,int l,int r){
    	//a[i].value ++;
    	if(a[i].l == l && a[i].r == r)
    		return a[i].value ;
    //	a[i].value ++; 
    	int mid = (a[i].l + a[i].r) / 2;
    	if(r <= mid)
    		return query(i<<1,l,r);
    	else if(l > mid)
    		return query((i<<1) + 1,l,r);
    	return query(i<<1,l,mid) + query((i<<1) + 1,mid+1,r);
    }
    
    void update(int i,int num){
    	a[i].value++ ;
    	if(a[i].l == a[i].r)
    		return ;
    	int mid = (a[i].l + a[i] .r) / 2;
    	if(num <= mid)
    		update(i<<1,num);
    	else
    		update((i<<1)+1,num);
    }
    
    int main(){
    	int i,j,ans[200010];
    	while(scanf("%d",&n) == 1 && n){
    		MAX = 0;
    		for(i=1;i<=n;i++){
    			scanf("%d%d",&s[i],&e[i]);
    			s[i] ++ ;
    			e[i] ++ ;
    			MAX = max(MAX,e[i]);
    		}
    		for(i=1;i<=n;i++)
    			r[i] = i;
    		sort(r+1,r+n+1,cmp);
    		buildtree(1,1,MAX);
    		for(i=1;i<=n;i++){
    			int t = r[i];
    			ans[t] = query(1,1,s[t]);
    			update(1,s[t]);
    			for(j=i-1;j>0;j--)
    				if(s[r[j]] == s[t] && e[r[j]] == e[t])
    					ans[t] -- ;
    				else
    					break;
    		}
    		for(i=1;i<n;i++)
    			printf("%d ",ans[i]);
    	   printf("%d
    ",ans[n]);	
    	}
    	return 0;
    }
    
  • 相关阅读:
    热安装NGINX并支持多站点SSL
    centos 自启动
    gulp入门
    nodejs的包管理器npm和cnpm
    Chrome扩展及应用开发
    dubbo本地搭建实例
    web项目中获取spring的bean对象
    Windows下zookeeper注册中心的安装和启动
    dubbo-admin管理控制台的安装和使用
    启动zookeeper报错:JAVA_HOME is not set
  • 原文地址:https://www.cnblogs.com/jxgapyw/p/4872455.html
Copyright © 2011-2022 走看看