[数据结构-线段树] poj 2528

在一面墙上贴海报,贴的顺序给出了,求最后能被看到的海报数量。

纯粹的线段树模拟题。

但数据范围给了10^7,超内存了。

实际上这里用了一个小技巧,虽然墙的宽度是很大的,但海报数量只有10000,所以这10^7个数中真正用到的数很少,这样的话就只需要把没用到的数给“删去”,剩下来的数从小到大映射为新的数,这样空间复杂度就大大降低了。

比如题目给的样例:

1 4
2 6
8 10
3 4
7 10
 
用到的数有:1 2 3 4 6 7 8 10
可以把它们映射为:
1 2 3 4 6 7 8 10
1 2 3 4 5 6 7 8

这样建树的时候只开到8就行了。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN=20010;
int seg[MAXN*2];//线段树的结点编号从0开始。
int lnext[MAXN*2],rnext[MAXN*2];
int l[MAXN*2],r[MAXN*2];
int tot;
int buildTree(int ll,int rr)
{
    int cur=tot++;
    l[cur]=ll;
    r[cur]=rr;
    if(ll==rr)
    {
        seg[cur] = 0;
        //printf("%d**\n",seg[cur]);
        lnext[cur]=rnext[cur]=-1;
        return cur;
    }
    int mid=(ll+rr)>>1;
    lnext[cur]=buildTree(ll,mid);
    rnext[cur]=buildTree(mid+1,rr);
    seg[cur]=0;
    return cur;
}
bool add(int cur,int ll,int rr,int val)
{
    if(rnext[cur]!=-1&&lnext[cur]&&seg[rnext[cur]]&&seg[lnext[cur]])  {
        seg[cur]=1;
    }
    if(seg[cur]) return false;
    if(ll>rr) swap(ll,rr);
    if(l[cur]==ll&&r[cur]==rr)
    {
        seg[cur]=val;
        return true;
    }
    bool s1=0,s2=0;
    int mid = (l[cur]+r[cur])>>1;
    if(ll>=mid+1)
        s1 = add(rnext[cur],ll,rr,val);
    else if(rr<=mid)
        s2 =  add(lnext[cur],ll,rr,val);
    else
    {
        s1=add(lnext[cur],ll,mid,val);
        s2=add(rnext[cur],mid+1,rr,val);
    }
    if(rnext[cur]!=-1&&lnext[cur]&&seg[rnext[cur]]&&seg[lnext[cur]])  {
        seg[cur]=1;
    }
    return s1||s2;
}

int data[10005][2];
int y[20005],cur,ying[10000002];
int main()
{
    int T,n,ans;
    scanf("%d",&T);
    while(T--&&scanf("%d",&n)!=EOF)
    {
        ans=0;cur=1;tot=0;
        for(int i=0;i<n;i++) {
            scanf("%d%d",&data[i][0],&data[i][1]);
            y[cur++]=data[i][0];
            y[cur++]=data[i][1];
        }
        y[0]=-1;
        sort(y+1,y+cur);
        int cc=1;
        for(int i=1;i<cur;i++) {
            if(y[i]==y[i-1]) continue;
            ying[y[i]]=cc++;
        }
        buildTree(1,cc-1);
        for(int i=n-1;i>=0;i--) {
            data[i][0]=ying[data[i][0]];
            data[i][1]=ying[data[i][1]];
            if(add(0,data[i][0],data[i][1],1)) ans++;
        }
        printf("%d\n",ans);
    }
}
时间: 2024-08-04 18:14:05

[数据结构-线段树] poj 2528的相关文章

HDU 4902 Nice boat(数据结构-线段树)

Nice boat Problem Description There is an old country and the king fell in love with a devil. The devil always asks the king to do some crazy things. Although the king used to be wise and beloved by his people. Now he is just like a boy in love and c

Chapter 3. 数据结构 线段树

Chapter 3. 数据结构 线段树 Sylvia's I.单点修改,区间查询. 模板: //单点修改 区间求和 //1操作 单点修改//2操作 区间求和 #include<cstdio> #include<iostream> using namespace std; #define MAXN 500005 int sum[MAXN<<2]; int n,m; void PushUp(int rt){//求和 sum[rt]=sum[rt<<1]+sum[

HDU 1394 Minimum Inversion Number (数据结构-线段树)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9514    Accepted Submission(s): 5860 Problem Description The inversion number of a given number sequence a1, a2, ..., an

线段树 POJ 3468

这周学习了一下线段树,偶遇POJ 3468,这道题是线段树区间更新,题意大概是有一段的长为n的数组,经过若干次对其中某一段的数进行加减,询问某一段的和.这题还是比较明显的线段树,如果细分到对每一个节点进行操作的话,复杂度为O(m^logn),容易超时,所以采取延迟标记的做法,直接对某一段进行操作,而暂不对其子树进行操作,话不多说,直接上代码吧 #include<cstdio> #include<cstring> #include<cstdlib> #include &l

每次输出有几条线段能完全覆盖大于自己和hdu5372相反 树状数组或线段树 poj 2481 Cows

http://poj.org/problem?id=2481 Cows Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 14762   Accepted: 4886 Description Farmer John's cows have discovered that the clover growing along the ridge of the hill (which we can think of as a one

两边点连直线求交点总数 树状数组或线段树 poj 3067 Japan

http://poj.org/problem?id=3067 Japan Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 23602   Accepted: 6369 Description Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island

数据结构---线段树

线段树 转载请注明出处,谢谢!http://blog.csdn.net/metalseed/article/details/8039326  持续更新中···   一:线段树基本概念 1:概述 线段树,类似区间树,是一个完全二叉树,它在各个节点保存一条线段(数组中的一段子数组),主要用于高效解决连续区间的动态查询问题,由于二叉结构的特性,它基本能保持每个操作的复杂度为O(lgN)! 性质:父亲的区间是[a,b],(c=(a+b)/2)左儿子的区间是[a,c],右儿子的区间是[c+1,b],线段树

离散化+线段树 POJ 3277 City Horizon

POJ 3277 City Horizon Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 18466 Accepted: 5077 Description Farmer John has taken his cows on a trip to the city! As the sun sets, the cows gaze at the city horizon and observe the beautiful silho

求左下角星星之和 树状数组或线段树 poj 2352 Stars

http://poj.org/problem?id=2352 Stars Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 37696   Accepted: 16419 Description Astronomers often examine star maps where stars are represented by points on a plane and each star has Cartesian coo