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

来源:互联网 发布:手弩 淘宝 编辑:程序博客网 时间:2024/05/14 12:11

方法一: 
这个方法是网上看到的,太犀利了。 从起点开始坐标是1 ,结束的后一位是-1 ,在for 循环里用S叠加表示每个位置凃了几次!!
#include<iostream>using namespace std;int qs[100002];void main(){int i,n,a,b,s;while(scanf("%d",&n),n){   for(i=1;i<=n;i++)   qs[i]=0;   for(i=0;i<n;i++)   {    scanf("%d%d",&a,&b);    qs[a]++;qs[b+1]--;   }   printf("%d",qs[1]);s=qs[1];   for(i=2;i<=n;i++)   {       s+=qs[i];       printf(" %d",s);   }   printf("/n");}}

方法二:
线段树,Creat();update();query(); 三个步骤。 nod[i].v表示从nod[i].l到nod[i].r被涂过的次数。
#include <iostream>using namespace std;#define MAXN 100001 struct {    int l,r,v;}nod[3*MAXN];int a[MAXN];void Creat(int t,int l,int r){    nod[t].l=l;    nod[t].r=r;    nod[t].v=0;    if (l==r)    {        return ;    }    int mid=(l+r) / 2;    Creat(2*t,l,mid);    Creat(2*t+1,mid+1,r);}void Update(int t,int l,int r){    if (l==nod[t].l&&r==nod[t].r)    {        nod[t].v++;        return ;    }    if (nod[t].v>0)    {        nod[2*t].v+=nod[t].v;        nod[2*t+1].v+=nod[t].v;        nod[t].v=0;    }    if (r<=nod[2*t].r)    {        Update(2*t,l,r);    }    else if (l>=nod[2*t+1].l)    {        Update(2*t+1,l,r);    }    else    {        Update(2*t,l,nod[2*t].r);        Update(2*t+1,nod[2*t+1].l,r);    }}int query(int t,int index){    if (nod[t].l==nod[t].r)    {        return nod[t].v;    }    int mid;    mid=(nod[t].l+nod[t].r)/2;    if (index<=mid)    {        return nod[t].v+query(2*t,index);    }    else{        return nod[t].v+query(2*t+1,index);    }}int main(){    int n;    int a,b;    while (cin>>n&&n)    {        int i;        Creat(1,1,n);        for (i=1;i<=n;i++)        {            cin>>a>>b;            Update(1,a,b);        }        int k;        for (i=1;i<=n;i++)        {            k=query(1,i);            cout<<k;            if (i==n)            {                cout<<endl;            }            else            {                cout<<" ";            }        }    }    return 0;}