1 1 1
3 2 1
这个题目在我们学校(ecjtu)比赛时没做出来,因为当时只学会了线段树单点更新与区间求和。
后来赛后连续做了两天的线段树,,,线段树水很深,我至今都还有很多技巧没有掌握,大家好好努力吧。
首先来看线段树代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define mem(str,x) memset(str,(x),sizeof(str))
#define mid (l+r)>>1
#define len (r-l+1)
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int maxn=100010;
int sum[maxn<<2],root[maxn<<2],n;
inline void pushup(int rt){
sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
inline void pushdown(int rt,int _len){
if(root[rt]){
int l=rt<<1,r=rt<<1|1,m=_len>>1;
root[l] += root[rt];
root[r] += root[rt];
sum[l] += (_len-m)*root[rt];
sum[r] +=m*root[rt];
root[rt] = 0;
}
}
void update(int left,int right,int l,int r,int rt)
{
if(left<=l && right>=r){
++root[rt];
sum[rt] += len;
return ;
}
pushdown(rt,len);
int m = mid;
if(left<=m) update(left,right,lson);
if(right>m) update(left,right,rson);
pushup(rt);
}
int query(int left,int right,int l,int r,int rt)
{
if(left==l && right==r) return sum[rt];
int m = mid;
pushdown(rt,len);
int s;
if(left<=m) s=query(left,right,lson);
else if(right>m) s=query(left,right,rson);
else s=(query(left,m,lson)+query(m+1,right,rson));
return s;
}
int main()
{
int a,b;
while(~scanf("%d",&n)&&n){
mem(sum,0);mem(root,0);///相当于建树的初始化。
for(int i=0;i<n;i++){
scanf("%d%d",&a,&b);
update(a,b,1,n,1);
}
for(int i=1;i<=n;i++){
printf("%d%c",query(i,i,1,n,1),i==n?'\n':' ');
}
}
return 0;
}
下面是树状树组的代码:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn 100000+10
int s[maxn];
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int c,int n)
{
while(x<=n){
s[x]+=c;
x+=lowbit(x);
}
}
int getsum(int x)
{
int sum=0;
while(x>0){
sum+=s[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int N;
while(scanf("%d",&N),N)
{
memset(s,0,sizeof(s));
for(int i=1;i<=N;i++)
{
int a,b;
scanf("%d%d",&a,&b);
update(a,1,N);
update(b+1,-1,N);
}
for(int i=1;i<=N;i++){
printf("%d%c",getsum(i),i==N?'\n':' ');
}
}
return 0;
}
下面是数组解决法(用到了dp思想):
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
#define maxn 100000+10
int s[maxn];
int main()
{
int N;
while(scanf("%d",&N),N){
memset(s,0,sizeof(s));
for(int i=1;i<=N;i++){
int a,b;
scanf("%d%d",&a,&b);
s[a]++;
s[b+1]--;
}
for(int i=1;i<=N;i++){
s[i]+=s[i-1];
printf("%d%c",s[i],i==N?'\n':' ');
}
}
return 0;
}