zoukankan      html  css  js  c++  java
  • POJ 2352 Stars (线段树)

    手动博客搬家:本文发表于20170819 22:11:49, 原地址https://blog.csdn.net/suncongbo/article/details/77417650

    URL: http://poj.org/problem?id=2352

    题目大意:给定n个点(n<=15000), 每个点有坐标(x, y) (0<=x, y<=32000), 规定每个点i的level等于满足x[j]<=x[i] && y[j]<=y[i]的点j的个数,求出level值为0, 1, 2, ..., n-1的点分别有几个. y以升序给出, y值相等的以x升序给出。

    思路分析:既然y值以升序给出,那问题就简化成了: 给定一个数列a, 求a[1]至a[i-1]共有多少个数在[0, i]之间。
    (然后统计一下即可)不难观察到,线段树很适合处理此类问题。
    把坐标看成区间,对[0,32000]的区间建线段树,树中的num记录[l, r]区间内的x的个数。
    (也可对[0,maxx]区间建树,但是要先求出maxx)每次添加新的节点,找到x应该所在的那个节点,然后沿着递归之路每到一个节点就num++, 直到找到为止。
    每次添加之前先询问,询问时求出区间[0,x]所跨子区间的num值之和。
    由此算出level, 然后统计即可。
    时间复杂度O(n log n).

    部分易错点:

    1. 线段树区间从0开始,而不是1.
    2. 线段树的数组要开MAXN的4倍,MAXN = 32000 but not 15000

    代码呈现:(Time: 188 MS; Memory: 2248 K; Code: 1452 B)

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    
    const int MAXN = 32000;
    struct Node
    {
    	int left,right,num,tag;
    };
    int lvl[MAXN+2];
    struct SegmentTree
    {
    	Node nd[MAXN*4+2];
    	
    	void init()
    	{
    		for(int i=1; i<=MAXN*4; i++)
    		{
    			nd[i].left = nd[i].right = nd[i].num = 0;
    		}
    	}
    	
    	void build(int lbound,int rbound,int pos)
    	{
    		nd[pos].left = lbound;
    		nd[pos].right = rbound;
    		if(lbound==rbound) return;
    		int mid = (lbound+rbound)/2;
    		build(lbound,mid,2*pos);
    		build(mid+1,rbound,2*pos+1);
    	}
    	
    	void addval(int lbound,int rbound,int val,int pos)
    	{
    		nd[pos].num++;
    		if(lbound==rbound) return;
    		int mid = (nd[pos].left+nd[pos].right)/2;
    		if(val<=mid) addval(lbound,mid,val,2*pos);
    		else addval(mid+1,rbound,val,2*pos+1);
    	}
    	
    	int query(int lbound,int rbound,int pos)
    	{
    		int mid = (nd[pos].left+nd[pos].right)/2;
    		if(lbound==nd[pos].left && rbound==nd[pos].right) return nd[pos].num;   
    		long long ans;
    		if(rbound<=mid) ans = query(lbound,rbound,2*pos);
    		else if(lbound>mid) ans = query(lbound,rbound,2*pos+1);
    		else ans = query(lbound,mid,2*pos)+query(mid+1,rbound,2*pos+1);
    		return ans;
    	}
    };
    SegmentTree st;
    int a[MAXN+2];
    int n;
    
    int main()
    {
    	int q,lbound,rbound,val;
    	char flag[5];
    	
    	scanf("%d",&n);
    	st.init();
    	st.build(0,MAXN,1); //can be both [0,MAXN] or [0,MAXX]; MAXX is the maximum value of all x
    	for(int i=1; i<=n; i++)
    	{
    		int x,y;
    		scanf("%d%d",&x,&y);
    		lvl[st.query(0,x,1)]++; //must be [0,x]
    		st.addval(0,MAXN,x,1);
    	}
    	for(int i=0; i<n; i++)
    	{
    		printf("%d
    ",lvl[i]);
    	} 
    	return 0;
    }
    
  • 相关阅读:
    获取汉字和字母的长度
    JavaScript 获取对象中第一个属性
    JS函数的length属性
    原型模式 -- JavaScript语言的灵魂
    建造者模式
    阻止form元素内的input标签回车提交表单
    工厂方法模式(安全的工厂方法)
    微信自研生产级paxos类库PhxPaxos实现原理介绍
    图解分布式一致性协议Paxos
    Paxos协议超级详细解释+简单实例
  • 原文地址:https://www.cnblogs.com/suncongbo/p/10182296.html
Copyright © 2011-2022 走看看