3 1 1 2 2 3 3 3 1 1 1 2 1 3 0
1 1 1 3 2 1
最近在写线段树,就用线段树写的,树状数组应该更简单
/** 线段树(区间更新): *线段树节点用来存储当前区间被涂过的颜色次数(注意这个次数不是实际次数,只保存当前区间被直接更新的次数) *全部更新一遍之后从最顶端被更新过的区间开始,一个节点一个节点的往下压,直到叶节点 *将叶节点的值转存到数组当中,输出。 */ #include<iostream> #include<stdio.h> #include<math.h> #include<string.h> using namespace std; const int N = 100005; int col[N << 2]; int Tree[N << 2]; void PushDown(int rt)//向下传递状态 { if(Tree[rt]) { Tree[rt << 1] += Tree[rt]; Tree[rt << 1 | 1] += Tree[rt]; Tree[rt] = 0; } } void Build(int l,int r,int rt) { Tree[rt] = 0; if(l == r) return; int mid = (l + r) >> 1; Build(l,mid,rt << 1); Build(mid + 1,r,rt << 1 | 1); } void Upgrade(int ll,int rr,int l,int r,int rt)//直接更新,即只更新输入数据直接代表的区间节点,不涉及最终状态 { if( ll <= l && r <= rr) { Tree[rt]++; return; } int mid = (l + r) >> 1; if(ll <= mid) Upgrade(ll,rr,l,mid,rt << 1); if(rr > mid) Upgrade(ll,rr,mid + 1,r,rt << 1 | 1); } void Query(int l,int r,int rt)//最后求叶节点最终状态时才调用PushDown函数,将所有有直接更新过的节点的值向下传递直至叶节点 { if(l == r) { col[r] = Tree[rt]; return; } PushDown(rt); int mid = (l + r) >> 1; Query(l,mid,rt << 1); Query(mid + 1,r,rt << 1 |1); } int main() { int n,a,b; while(scanf("%d",&n) != EOF && n != 0) { Build(1,n,1); memset(col,0,sizeof(col)); for(int i = 0; i < n; i++) { scanf("%d%d",&a,&b); Upgrade(a,b,1,n,1); } Query(1,n,1); for(int j = 1; j <= n; j++)//注意最后输出的格式 { if(j != n) printf("%d ",col[j]); else printf("%d\n",col[j]); } } return 0; }