J - Super Mario HDU - 4417
这个题目我开始直接暴力,然后就超时了,不知道该怎么做,直接看了题解,这个习惯其实不太好。
不过网上的思路真的很厉害,看完之后有点伤心,感觉自己应该可以写的,但是没有写出来。
因为我们要查找一个区间小于等于c的数有多少个,这种区间处理可以用线段树很好的解决,
但是怎么解决呢,我习惯性的直接建树,然后再想怎么做,其实这样不对,
线段树对于我们来说是一个解决问题的工具,不要本末倒置了。
我们想查找一个区间小于等于c的数的个数,用线段树查询很简单,但是怎么建树才可以
让我们每次查询都得到想要的结果呢,这个肯定是不能直接把这个墙的高度直接建树的,应该要先处理一下。
我们可以把查询的高度按升序排序,这样线段树之前更新过的值就不会影响后面的值了。
但是线段树怎么更新呢,这个也可以按升序对墙排个序,这样就解决问题了。
这个思路其实没有特别难想。。。
代码很好敲,但是要注意不要漏掉了,也许都已经更新完了,但是这个答案没有在for循环里面找到。
这个要注意!!!
然后这个题目还可以用主席树写
#include <cstdio> #include <cstring> #include <cstdlib> #include <queue> #include <vector> #include <algorithm> #include <iostream> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; typedef long long ll; const int maxn = 2e5+10; ll sum[maxn*8], ans[maxn]; int n, m; struct node { ll num, id; }a[maxn]; struct edge { ll l, r, h, id; edge(ll l=0,ll r=0,ll h=0,ll id=0):l(l),r(r),h(h),id(id){} }ex[maxn]; bool cmp(node a,node b) { return a.num < b.num; } bool cmp1(edge a,edge b) { return a.h < b.h; } void update(int id,int l,int r,int pos) { if(l==r) { sum[id] = 1; return; } int mid = (l + r) >> 1; if (pos <= mid) update(id << 1, l, mid, pos); else update(id << 1 | 1, mid + 1, r, pos); sum[id] = sum[id << 1] + sum[id << 1 | 1]; //printf("sum[%d]=%d ", id, sum[id]); } ll query(int id,int l,int r,int x,int y) { if (x <= l && y >= r) return sum[id]; int mid = (l + r) >> 1; int ans = 0; if (x <= mid) ans += query(id << 1, l, mid, x, y); if (y > mid) ans += query(id << 1 | 1, mid + 1, r, x, y); return ans; } int main() { int t; scanf("%d", &t); for(int cas=1;cas<=t;cas++) { memset(ans, 0, sizeof(ans)); memset(sum, 0, sizeof(sum)); scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%lld", &a[i].num), a[i].id = i; for (int i = 1; i <= m; i++) { ll l, r, h; scanf("%lld%lld%lld", &l, &r, &h); l++, r++; ex[i] = edge(l, r, h, i); } sort(a + 1, a + 1 + n, cmp); sort(ex + 1, ex + 1 + m, cmp1); printf("Case %d: ", cas); int k = 1; for(int i=1;i<=n;i++) { while(a[i].num>ex[k].h&&k<=m) { ans[ex[k].id] = query(1, 1, n, ex[k].l, ex[k].r); k++; } update(1, 1, n, a[i].id); } for (int i = k; i <= m; i++) ans[ex[i].id] = query(1, 1, n, ex[i].l, ex[i].r);//这个注意不要丢掉了!!! for (int i = 1; i <= m; i++) printf("%lld ", ans[i]); } return 0; }
#include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <queue> #include <vector> #define inf 0x3f3f3f3f #define inf64 0x3f3f3f3f3f3f3f3f using namespace std; const int maxn = 1e5 + 10; int n, m, root[maxn], a[maxn], b[maxn], cnt; int sum[maxn << 5], lc[maxn << 5], rc[maxn << 5]; void build(int &rt,int l,int r) { rt = ++cnt; sum[rt] = 0; if (l == r) return; int mid = (l + r) >> 1; build(lc[rt], l, mid); build(rc[rt], mid + 1, r); // printf("rt=%d l=%d r=%d ",rt,l,r); } int update(int rt,int l,int r,int pos) { // printf("ww rt=%d l=%d r=%d pos=%d ", rt, l, r, pos); int id = ++cnt; sum[id] = sum[rt] + 1; // printf("rt=%d sum[%d]=%d ", rt, id, sum[id]); lc[id] = lc[rt], rc[id] = rc[rt]; if (l == r) return id; int mid = (l + r) >> 1; // printf("mid=%d rt=%d l=%d r=%d pos=%d ", mid,rt,l,r,pos); if (pos <= mid) lc[id] = update(lc[id], l, mid, pos); else rc[id] = update(rc[id], mid + 1, r, pos); // printf("rt=%d l=%d r=%d pos=%d ", rt, l, r, pos); return id; } int query(int l,int r,int u,int v,int h) { int mid = (l + r) >> 1; int x = sum[lc[v]] - sum[lc[u]]; if (l == r) return sum[v] - sum[u]; int ans = 0; if (h <= mid) ans = query(l, mid, lc[u], lc[v], h); else ans = x + query(mid + 1, r, rc[u], rc[v], h); return ans; } int main() { int t; scanf("%d", &t); for(int cas=1;cas<=t;cas++) { cnt = 0; scanf("%d%d", &n, &m); for (int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i]; sort(b + 1, b + 1 + n); int len = unique(b + 1, b + 1 + n) - b - 1; build(root[0], 1, len); // printf(" "); for (int i = 1; i <= n; i++) { a[i] = lower_bound(b + 1, b + 1 + len, a[i]) - b; //printf("a[%d]=%d ", i, a[i]); root[i] = update(root[i - 1], 1, len, a[i]); // printf("sum[%d]=%d ", root[i], sum[root[i]]); // printf(" "); } printf("Case %d: ", cas); while(m--) { int l, r, h; scanf("%d%d%d", &l, &r, &h); l++, r++; h = upper_bound(b + 1, b + 1 + len, h) - b - 1; if (h == 0) printf("0 "); else printf("%d ", query(1, len, root[l - 1], root[r], h)); } } return 0; }