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+;
ll sum[maxn*], ans[maxn];
int n, m;
struct node
{
ll num, id;
}a[maxn];
struct edge
{
ll l, r, h, id;
edge(ll l=,ll r=,ll h=,ll id=):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] = ;
return;
}
int mid = (l + r) >> ;
if (pos <= mid) update(id << , l, mid, pos);
else update(id << | , mid + , r, pos);
sum[id] = sum[id << ] + sum[id << | ];
//printf("sum[%d]=%d\n", 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) >> ;
int ans = ;
if (x <= mid) ans += query(id << , l, mid, x, y);
if (y > mid) ans += query(id << | , mid + , r, x, y);
return ans;
} int main()
{
int t;
scanf("%d", &t);
for(int cas=;cas<=t;cas++)
{
memset(ans, , sizeof(ans));
memset(sum, , sizeof(sum));
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) scanf("%lld", &a[i].num), a[i].id = i;
for (int i = ; 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 + , a + + n, cmp);
sort(ex + , ex + + m, cmp1);
printf("Case %d:\n", cas);
int k = ;
for(int i=;i<=n;i++)
{
while(a[i].num>ex[k].h&&k<=m)
{
ans[ex[k].id] = query(, , n, ex[k].l, ex[k].r);
k++;
}
update(, , n, a[i].id);
}
for (int i = k; i <= m; i++) ans[ex[i].id] = query(, , n, ex[i].l, ex[i].r);//这个注意不要丢掉了!!!
for (int i = ; i <= m; i++) printf("%lld\n", ans[i]);
}
return ;
}

线段树

#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 + ;
int n, m, root[maxn], a[maxn], b[maxn], cnt;
int sum[maxn << ], lc[maxn << ], rc[maxn << ]; void build(int &rt,int l,int r)
{
rt = ++cnt;
sum[rt] = ;
if (l == r) return;
int mid = (l + r) >> ;
build(lc[rt], l, mid);
build(rc[rt], mid + , r);
// printf("rt=%d l=%d r=%d\n",rt,l,r);
} int update(int rt,int l,int r,int pos)
{
// printf("ww rt=%d l=%d r=%d pos=%d\n", rt, l, r, pos);
int id = ++cnt;
sum[id] = sum[rt] + ;
// printf("rt=%d sum[%d]=%d\n", rt, id, sum[id]);
lc[id] = lc[rt], rc[id] = rc[rt];
if (l == r) return id;
int mid = (l + r) >> ;
// printf("mid=%d rt=%d l=%d r=%d pos=%d\n", mid,rt,l,r,pos);
if (pos <= mid) lc[id] = update(lc[id], l, mid, pos);
else rc[id] = update(rc[id], mid + , r, pos);
// printf("rt=%d l=%d r=%d pos=%d\n", rt, l, r, pos);
return id;
} int query(int l,int r,int u,int v,int h)
{
int mid = (l + r) >> ;
int x = sum[lc[v]] - sum[lc[u]];
if (l == r) return sum[v] - sum[u];
int ans = ;
if (h <= mid) ans = query(l, mid, lc[u], lc[v], h);
else ans = x + query(mid + , r, rc[u], rc[v], h);
return ans;
} int main()
{
int t;
scanf("%d", &t);
for(int cas=;cas<=t;cas++)
{
cnt = ;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];
sort(b + , b + + n);
int len = unique(b + , b + + n) - b - ;
build(root[], , len);
// printf("\n\n");
for (int i = ; i <= n; i++) {
a[i] = lower_bound(b + , b + + len, a[i]) - b;
//printf("a[%d]=%d\n", i, a[i]);
root[i] = update(root[i - ], , len, a[i]);
// printf("sum[%d]=%d\n", root[i], sum[root[i]]);
// printf("\n");
}
printf("Case %d:\n", cas);
while(m--)
{
int l, r, h;
scanf("%d%d%d", &l, &r, &h);
l++, r++;
h = upper_bound(b + , b + + len, h) - b - ;
if (h == ) printf("0\n");
else printf("%d\n", query(, len, root[l - ], root[r], h));
}
}
return ;
}

主席树

J - Super Mario HDU - 4417 线段树 离线处理 区间排序的更多相关文章

  1. Super Mario HDU 4417 主席树区间查询

    Super Mario HDU 4417 主席树区间查询 题意 给你n个数(编号从0开始),然后查询区间内小于k的数的个数. 解题思路 这个可以使用主席树来处理,因为这个很类似查询区间内的第k小的问题 ...

  2. E - No Pain No Game 线段树 离线处理 区间排序

    E - No Pain No Game  HDU - 4630 这个题目很好,以后可以再写写.这个题目就是线段树的离线写法,推荐一个博客:https://blog.csdn.net/u01003321 ...

  3. Super Mario HDU - 4417 (主席树询问区间比k小的个数)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  4. hdu 1166线段树 单点更新 区间求和

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  5. AC日记——Super Mario hdu 4417

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  6. HDU 3308 线段树单点更新+区间查找最长连续子序列

    LCIS                                                              Time Limit: 6000/2000 MS (Java/Oth ...

  7. Super Mario HDU - 4417 (主席树)

    Mario is world-famous plumber. His “burly” figure and amazing jumping ability reminded in our memory ...

  8. hdu 4288 线段树+离线+离散化

    http://acm.hdu.edu.cn/showproblem.php?pid=4288 開始的时候,果断TLE,做的方法是,线段树上只维护%5==3的坐标,比方1 2 3 4 5 6 7  假设 ...

  9. I Hate It HDU - 1754 线段树 单点修改+区间最值

    #include<iostream> #include<cstring> using namespace std; ; int m,n,p; struct node{ int ...

随机推荐

  1. 数论-质因数(gcd) UVa 10791 - Minimum Sum LCM

    https://vjudge.net/problem/UVA-10791/origin 以上为题目来源Google翻译得到的题意: 一组整数的LCM(最小公倍数)定义为最小数,即 该集合的所有整数的倍 ...

  2. Thinking in Java,Fourth Edition(Java 编程思想,第四版)学习笔记(五)之Controlling Execution

    In Java, the keywords include if-else,while,do-while,for,return,break, and a selection statement cal ...

  3. G - Harmonic Number (II) LightOJ - 1245

    算是一个找规律的题目吧. 枚举前sqrt(n)个数,数i出现的次数为n/i-n/(i+1),对答案的贡献为(n/i-n/(i+1))*i. 对于sqrt后边的数,可以直接由n/i获得,并且一定只出现一 ...

  4. D - Harmonious Graph

    题目大意: n个点,m条边,两个数l和r,如果l和r相连接,那么对于l和r之间值任意一个数都要和l相连.问达到这一目的需要添加的边的最小数量. 题解: 我们首先要找到当前连通块中最大的那个点,也就是说 ...

  5. sftp的用法

    linux sftp远程连接命令 sftp -oPort=60001 root@192.168.0.254 使用-o选项来指定端口号. -oPort=远程端口号 sftp> get /var/w ...

  6. Apache solr velocity模块 漏洞复现

    0x01 Solr简单介绍 Solr是建立在Apache Lucene ™之上的一个流行.快速.开放源代码的企业搜索平台. Solr具有高度的可靠性,可伸缩性和容错能力,可提供分布式索引,复制和负载平 ...

  7. srt字幕翻译

    需要把字幕名改成i.txt 有有道和谷歌 代码: #Author:Chenglong Qian #Copyright :Chenglong Qian import json import reques ...

  8. Java中接口的概念

    接口的特点: A:接口用关键字interface表示 interface 接口名 {} B:类实现接口用 implements 表示 class 类名 implements 接口名 {} C:接口不能 ...

  9. Spiking-YOLO : 前沿性研究,脉冲神经网络在目标检测的首次尝试 | AAAI 2020

    论文提出Spiking-YOLO,是脉冲神经网络在目标检测领域的首次成功尝试,实现了与卷积神经网络相当的性能,而能源消耗极低.论文内容新颖,比较前沿,推荐给大家阅读   来源:晓飞的算法工程笔记 公众 ...

  10. 巧用Grafana和Arthas自动抓取K8S中异常Java进程的线程堆栈

    前言 近期发现业务高峰期时刻会出现CPU繁忙导致的timeout异常,通过监控来看是因为Node上面的一些Pod突发抢占了大量CPU导致的. 问: 没有限制CPU吗?是不是限制的CPU使用值就可以解决 ...