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

题目地址:点击打开链接

参考的大神的代码地址:地址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;
}



你可能感兴趣的:(HDU 1556 Color the ball(区间标记或者线段树))