0
点赞
收藏
分享

微信扫一扫

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

文风起武 2022-08-04 阅读 37


题目地址:​​点击打开链接​​

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

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 条评论