题目地址:点击打开链接
参考的大神的代码地址:地址1:点击打开链接 地址2:点击打开链接
思路:还是和线段树模板有点区别的,不用记录增量,因为对所有的数据都要查询,树的节点不是保留这一段的和,而是保留这一段增加的次数,便于输出最后每个数据的值,地址一是递归输出,挺厉害的
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; }