http://acm.hdu.edu.cn/showproblem.php?pid=1556

这道杭电题以前有点不懂,但是现在懂了。。终于懂了。。附代码,三种方法哦!!!呵呵呵;见代码吧!!具体问题见代码分析!!

方法一:(也是做容易想到的,线段树。)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=111111;
int sum,root[N<<2];
int n;
void update(int l,int r,int rt,int x,int y)
{
    if(x<=l&&y>=r)
    {
        root[rt]++;
        return ;
    }
    int m=(l+r)>>1;
    if(x>m) update(m+1,r,rt*2+1,x,y);//实际这几个if else语句可以转化为:/*if(x<=m) query(l,m,rt*2,x,y);else if(y>m)  query(m+1,r,rt*2+1,x,y);*/
    else  if(y<=m)  update(l,m,rt*2,x,y);//   这样更易理解,,,
    else
    {
        update(l,m,rt*2,x,y);
        update(m+1,r,rt*2+1,x,y);
    }
}
void query(int l,int r,int rt,int sum)
{
    if(l==r)
    {
       printf("%d%c",sum+root[rt],l==n?'\n':' ');
       return ;
    }
    int m=(l+r)>>1;
    query(l,m,rt*2,sum+root[rt]);
    query(m+1,r,rt*2+1,sum+root[rt]);
}
int main()
{
    while(scanf("%d",&n)!=EOF)
    {
        if(n==0)break;
        memset(root,0,sizeof(root));
        int x,y;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            update(1,n,1,x,y);
        }
        query(1,n,1,0);
    }
    return 0;
}
方法二:(也是利用线段树,加上了结构体,可能理解上会有点难。)
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef struct n
{
    int l;
    int r;
    int color;
} T;
T tree[500000];
int flag[100010];
void make_tree(int l,int r,int rt )
{
    //if(tree[rt].l==tree[rt].r)
    //  {
    //     return ;
    // }
    tree[rt].l=l;
    tree[rt].r=r;
    tree[rt].color=0;
    if(l!=r)
    {
        int m=(l+r)>>1;
        make_tree(l,m,rt*2);
        make_tree(m+1,r,rt*2+1);
    }
}
void update(int l,int r,int rt)
{
    if(l<=tree[rt].l&&r>=tree[rt].r)
    {
        tree[rt].color++;
        return ;
    }
    else
    {
        int m=(tree[rt].l+tree[rt].r)>>1;
        if(l>m)
            update(l,r,rt*2+1);
        else
        {
            if(r<=m)
                update(l,r,rt*2);
            else
            {
                update(l,m,rt*2);
                update(m+1,r,rt*2+1);
            }
        }
    }
}
void count(int x)
{
    if(tree[x].l==tree[x].r)
    {
        flag[tree[x].l]=tree[x].color;
        return  ;
    }
    tree[2*x].color+=tree[x].color;
    tree[2*x+1].color+=tree[x].color;
    count(2*x);
    count(2*x+1);
}
int main()
{
    int i,n;
    while(scanf("%d",&n)!=EOF&&n)
    {
        make_tree(1,n,1);
        int x,y;
        for(i=1; i<=n; i++)
        {
            scanf("%d%d",&x,&y);
            update(x,y,1);
        }
        memset(flag,0,sizeof(flag));
        count(1);
        for(i=1; i<n; i++)
      //  {
            printf("%d ",flag[i]);
           // if(i==n-1)
                printf("%d\n",flag[i]);
      // }
    }
    return 0;
}

 
方法三(利用数组解决,但是这里有个小技巧要注意下,否则在一般情况下会超时。。)
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int main()
{
    int i,n,a,b;
    int f[100005];
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(f,0,sizeof(f));
        for(i=0;i<n;i++)
        {
            scanf("%d%d",&a,&b);   需要注意的就是这里,一下就是小技巧。
            f[a]++;         //并不是把每一个的更新的区间每一个数都变化,显然那样会超时,那是绝对的,所以就直接对一头一尾的数进行处理,这样每一个数都和前一个数有关。但
//但是还有就是在最后一个数时,必须向后移动一位,这个技巧自己慢慢领会。且最后一个数是减1的。
            f[b+1]--;
        }
        for(i=1;i<=n;i++)
        {
            f[i]+=f[i-1];          //这里也是需要注意的,因为在前面,不是一头的数加了1吗!!所以更具有点dp的思想,进行加。这样就是每一个数都和它前一个数有关。
            if(i>1)cout<<' ';
            cout<<f[i];
        }
            cout<<endl;
    }
    return 0;
}





 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值