//线段树
#include <stdio.h>
#include <string.h>
typedef struct node node;
struct node
{
int l,r,sum;
};
node ball[300000];
int n;
void BuildTree(int t, int l, int r)
{
ball[t].l = l;
ball[t].r = r;
ball[t].sum = 0;
if(l == r) return;
int mid = (l+r) >> 1;
BuildTree(t<<1, l, mid);
BuildTree(t<<1|1, mid+1, r);
}
void Updata(int t, int l, int r)
{
if(ball[t].l == l && ball[t].r == r)
{
++ball[t].sum;
return ;
}
if(ball[t].l == ball[t].r)
return;
int mid = (ball[t].l + ball[t].r) >> 1;
if(mid >= r)
Updata(t<<1, l, r);
else if(mid < l)
Updata(t<<1|1, l, r);
else
{
Updata(t<<1, l, mid);
Updata(t<<1|1, mid+1, r);
}
}
int Query(int t, int l, int r)
{
if(ball[t].l == l && ball[t].r == r)
return ball[t].sum;
if(ball[t].l == ball[t].r)
return 0;
int mid = (ball[t].l + ball[t].r) >> 1;
if(r <= mid)
return ball[t].sum + Query(t<<1, l, r);
else if(l > mid)
return ball[t].sum + Query(t<<1|1, l, r);
else return ball[t].l + Query(t<<1, l, r) + Query(t<<1|1, l, r);
}
int main()
{
int x,y;
memset(ball, 0, sizeof(ball));
while(scanf("%d",&n) && n)
{
BuildTree(1, 1, n);
for(int i = 0; i < n; ++i)
{
scanf("%d %d",&x,&y);
Updata(1, x, y);
}
for(int i = 0; i < n; ++i)
{
printf("%d",Query(1,i+1,i+1));
if(i != n-1)
printf(" ");
else
printf("\n");
}
}
return 0;
}
树状数组
和下边前缀和一样,也是前缀和的思想,实现方式不同
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100100;
int ball[MAXN];
int N,a,b;
int lowBit(int x)
{
return x&(-x);
}
int sum(int i)
{
int s = 0;
while(i > 0)
{
s += ball[i];
i -= lowBit(i);
}
return s;
}
void add(int i, int x)
{
while(i <= N)
{
ball[i] += x;
i += lowBit(i);
}
}
int main()
{
ios::sync_with_stdio(false);
while(cin >> N && N)
{
memset(ball,0,sizeof(ball));
for(int i = 0; i < N; ++i)
{
cin >> a >> b;
add(a,1);
add(b+1,-1);
}
for(int i = 1; i < N; ++i)
cout << sum(i) << " ";
cout << sum(N) << endl;
}
return 0;
}
涂色(a,b)区间,则只要a出为1,b+1出为-1,就可以求前缀和时让这种颜色只在(a,b)区间有影响
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100100;
int ball[MAXN];
int preSum[MAXN];
int N,a,b;
int main()
{
ios::sync_with_stdio(false);
while(cin >> N && N)
{
memset(ball,0,sizeof(ball));
memset(preSum,0,sizeof(preSum));
for(int i = 0; i < N; ++i)
{
cin >> a >> b;
ball[a] += 1;
ball[b+1] += -1;
}
int res = 0;
for(int i = 1; i < N; ++i)
{
preSum[i] = preSum[i-1]+ball[i];
cout << preSum[i] << " ";
}
cout << preSum[N-1]+ball[N] << endl;
}
return 0;
}