HDU 1556 Color the ball(区间标记或者线段树)

来源:互联网 发布:游戏自动优化软件 编辑:程序博客网 时间:2024/06/06 12:39

题目地址:点击打开链接

参考的大神的代码地址:地址1:点击打开链接 地址2:点击打开链接

思路:还是和线段树模板有点区别的,不用记录增量,因为对所有的数据都要查询,树的节点不是保留这一段的和,而是保留这一段增加的次数,便于输出最后每个数据的值,地址一是递归输出,挺厉害的

AC代码:

#include <iostream>#include<cstring>using namespace std;struct trees{    int l;    int r;    int time;}tree[1000000];//必须比数据给的数据大,因为是建树int cf[100010];void bulid(int v,int l,int r){    int mid;    tree[v].l = l;    tree[v].r = r;    tree[v].time = 0;    if(l != r)    {        mid = (l + r) / 2;        bulid(v*2,l,mid);        bulid(v*2+1,mid+1,r);    }}void update(int v,int l,int r){    int mid;    if(tree[v].l == l && tree[v].r == r)    {        tree[v].time++;        return;    }    mid = (tree[v].l + tree[v].r) / 2;    if(r <= mid)        update(v*2,l,r);    else if(l > mid)        update(v*2+1,l,r);    else    {        update(v*2,l,mid);        update(v*2+1,mid+1,r);    }}void add(int x)//把父节点涂色的次数传递到子节点{    int i;    for(i=tree[x].l; i<=tree[x].r; i++)    {        cf[i] += tree[x].time;    }    if(tree[x].l == tree[x].r)        return;    add(x*2);    add(x*2+1);}int main(){   int n,a,b,i;   while(cin>>n && n)   {       bulid(1,1,n);       for(i=1; i<=n; i++)       {           cin>>a>>b;           update(1,a,b);       }       memset(cf,0,sizeof(cf));       add(1);       cout<<cf[1];       for(i=2; i<=n; i++)       {           cout<<" "<<cf[i];       }       cout<<endl;   }   return 0;}

思路:队友教的思想,这道题改的次数多,查的次数少,可以吧一段区间的左边+1,一段区间的右边-1,最后查一个气球被涂了几次就可以把他左边的数加起来,就是他被涂的次数,一段区间如果没有包括这个气球则这个区间的-1和+1的和正好是0,或者只加了区间左边的+1,右边的-1没有加

AC代码2:

#include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <queue>#include <stack>#include <map>#include <cstring>#include <climits>#include <cmath>#include <cctype>typedef long long ll;using namespace std;int dp[100010];int cf[100010];int main(){    int n;    int a,b,i;    while(scanf("%d",&n) && n)    {        memset(dp,0,sizeof(dp));        memset(cf,0,sizeof(a));        for(i=0; i<n; i++)        {            scanf("%d%d",&a,&b);            dp[a-1] += 1;//左端+1            dp[b] -= 1;//右端-1.注意下标        }        cf[1] = dp[0];        for(i=2; i<=n; i++)        {            cf[i] = dp[i-1] + cf[i-1];        }        printf("%d",cf[1]);        for(i=2; i<=n; i++)        {            printf(" %d",cf[i]);        }        printf("\n");    }    return 0;}

学弟写的,开了一个数组

AC代码:

#include <iostream>#include<string.h>#include<cstring>using namespace std;int main(){    int s[100000],N,a,b,sum;    while (cin >> N,N)    {        memset(s, 0, sizeof(s));                for (int i = 1; i <= N; i++)        {            cin >> a >> b;            s[a-1]++;            s[b]--;        }        sum = 0;        for (int i = 1; i <= N; i++)        {            int c = s[i];            s[i] = sum + s[i - 1];            sum = c;        }        for (int i = 1; i <= N; i++)        {            if (i == 1) cout << s[i];            else cout <<" "<<s[i];        }        cout << endl;    }    return 0;}



0 0
原创粉丝点击