题目链接:点击打开链接
思路:简单的线段树模板,理解了好久。创建+更新+查询。更新只涉及到区间更新次数(+1)即可。查询可以递归查询,累加包含查询结点的树结点(即离散化的区间[l,r])的次数即可。简单的说就是,查询结点所在的区间更新次数的总和。
eg:离散化到树结点,若共有4个结点,更新区间[1,3]则更新到区间[1,2]+[3,3].
#include <iostream> #include <cstring> #include <cstdio> #include <cmath> using namespace std; struct Node{ int l,r; int sum; //sum表示整个区间 [l,r] 被维护的次数。一定是整个区间,且被离散化到各个树结点的子区间 }node[400005]; void build(int id,int l,int r){ node[id].l = l; node[id].r = r; node[id].sum = 0; if(l == r) return ; int mid = (l+r) >> 1; build(id*2,l,mid); build(id*2+1,mid+1,r); } void update(int id,int l,int r){ if(node[id].l == l && node[id].r == r){ node[id].sum++; return ; } int mid = node[id].l+node[id].r >> 1; if(r <= mid) update(id*2,l,r); else if(l > mid) update(id*2+1,l,r); else{ update(id*2,l,mid); update(id*2+1,mid+1,r); } } int ans; void query(int id,int temp){ ans += node[id].sum; if(node[id].l == node[id].r && node[id].l == temp) return ; int mid = (node[id].l + node[id].r) >> 1; if(temp <= mid) query(2*id,temp); else query(2*id+1,temp); } int main() { int n; while(cin>>n,n != 0){ int l,r; build(1,1,n); for(int i = 1;i <= n;i ++){ scanf("%d%d",&l,&r); update(1,l,r); } for(int i = 1;i <= 15;i ++) cout<<node[i].l<<" "<<node[i].r<<" "<<node[i].sum<<endl; for(int i = 1;i <= n;i ++){ if(i != 1) cout<<" "; ans = 0; query(1,i); cout<<ans; } cout<<endl; } return 0; }