Hdu-3333 Turning Tree (离线树状数组/线段树)
题目大意:先给出n个数字。面对q个询问区间,输出这个区间不同数的和。
题解:这道题有多重解法。我另一篇博客写了分块的解法 HDU-3333 Turing Tree 分块求区间不同数和 。
这里讲一下离线树状数组或者线段树的解法。
先讲一下我们在线(按询问顺序)做这道题会有什么麻烦。因为一个区间重复的数我们只算一个,那么我们认为对于一个区间,重复的数我们只算最接近区间右段点的哪一个。但是因为按询问顺序,它的右端点是会起伏的。所以我们不好统计到底对于每一个询问区间,哪一个才是该区间重复数中有效的哪一个。
那么我们转变一下思路。改成离线算法。先把询问区间按右端点排序。那么因为区间右段点的单调性,按照这个顺序我们可以只算重复数的最右边的那个。
具体做法是排序询问右端点r,把1-r的数都加入到树状数组。如果该数在前面有重复数last[i]。那么就把last[i]的值在树状数组去掉,把r点的值在树状数组上加上。那么保证在1-r内每个数只会出现一次。
AC代码如下:
#include<iostream>
#include<cstdio>
#include<map>
#include<algorithm>
using namespace std;
const int N=+;
const int M=+;
struct node{
int x,y,num;
bool operator < (const node& t) {
return y<t.y;
}
}q[M];
int n,m,a[N];
long long sum[*N],ans[M],last[N];
map<int,int> lst; int lowbit(int x) { return x&(-x); } void update(int x,int v) {
while (x<=n) {
sum[x]+=v;
x+=lowbit(x);
}
} long long query(int x) {
long long ans=;
while (x) {
ans+=sum[x];
x-=lowbit(x);
}
return ans;
} int main()
{
int T;
scanf("%d",&T);
while (T--) {
scanf("%d",&n);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
lst.clear();
for (int i=;i<=n;i++) last[i]=;
for (int i=;i<=n;i++) {
last[i]=lst[a[i]];
lst[a[i]]=i;
} scanf("%d",&m);
for (int i=;i<=m;i++) {
scanf("%d%d",&q[i].x,&q[i].y);
q[i].num=i;
} sort(q+,q+m+);
int now=;
for (int i=;i<=n;i++) sum[i]=;
for (int i=;i<=m;i++) {
while (now<q[i].y) {
now++;
update(now,a[now]);
if (last[now]) update(last[now],-a[now]);
}
ans[q[i].num]=query(q[i].y)-query(q[i].x-);
}
for (int i=;i<=m;i++) printf("%lld\n",ans[i]);
}
return ;
}
Hdu-3333 Turning Tree (离线树状数组/线段树)的更多相关文章
- 树状数组 && 线段树应用 -- 求逆序数
参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...
- hdu1394(枚举/树状数组/线段树单点更新&区间求和)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...
- 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树
正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...
- hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submis ...
- hdu 5147 Sequence II【树状数组/线段树】
Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...
- hdu 3966 Aragorn's Story(树链剖分+树状数组/线段树)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3966 题意: 给出一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路 ...
- BZOJ 3333 排队计划 树状数组+线段树
题目大意:给定一个序列.每次选择一个位置,把这个位置之后全部小于等于这个数的数抽出来,排序,再插回去,求每次操作后的逆序对数 首先我们每一次操作 对于这个位置前面的数 因为排序的数与前面的数位置关系不 ...
- hdu 1166 敌兵布阵——(区间和)树状数组/线段树
pid=1166">here:http://acm.hdu.edu.cn/showproblem.php?pid=1166 Input 第一行一个整数T.表示有T组数据. 每组数据第一 ...
- HDU 1166 敌兵布阵 树状数组||线段树
http://acm.hdu.edu.cn/showproblem.php?pid=1166 题目大意: 给定n个数的区间N<=50000,还有Q个询问(Q<=40000)求区间和. 每个 ...
随机推荐
- Elastic Search快速入门
https://blog.csdn.net/weixin_42633131/article/details/82902812 通过这个篇文章可以快速入门,快速搭建一个elastic search de ...
- css 当文字过多时以....省略
<!-- 公告 --> <p class="rst-promotion">公告: {{shopInfo.rst.promotion_info}}</p ...
- Codeforces 958F2 Lightsabers (medium) 尺取法
题目大意: 输入n,m,分别表示人的个数和颜色的个数,下一行输入n个数,对应每个人的颜色,最后一行输入对应每个颜色的人应有的数量: 问是否能找出一个区间,满足条件但有多余的人,输出多余的人最少的个数, ...
- Nginx1.6.0+MySQL5.6.19+PHP5.5.14(centos)
一.配置防火墙,开启80端口.3306端口 CentOS 7.0默认使用的是firewall作为防火墙,这里改为iptables防火墙. 1.关闭firewall: systemctl stop fi ...
- Java中的String、StringBuffer、StringBuilder区别以及Java之StringUtils的用法
1.String.StringBuffer.StringBuilder的区别 String是Java中基础类型,是immutable类(不可变)的典型实现,利用string进行拼接是会产生过多无用对象 ...
- vuejs如何调试代码
基于webpack的配置调试 使用Vue-cli命令行工具初始化基于wabpack模板的项目的命令语法: npm install -g @vue/cli # 全局安装vue-cli,版本vue3.x ...
- 【转】从phpMyAdmin批量导入Excel内容到MySQL(亲测非常简洁有效)
今天做项目遇到需要用phpMyAdmin批量导入Excel内容到MySQL数据库.分析了我的踏坑经历并且总结一最便捷的一套导入数据的方法,非常实用简洁: 1.修改Excel表的数据,使得Excel中的 ...
- solr测试用的配置
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.spr ...
- 英语单词Uninterrupted
Uninterrupted 来源——不间断电源供应 UPS(Uninterrupted Power Supply) 翻译 adj. 不间断的:连续的 GRE 词根 un- + interrupt ...
- Java Web学习总结(8)JSP(二)
一,JSP中的九个内置对象 名称 类型 描述 out javax.servlet.jsp.JspWriter 用于页面输出 request javax.servlet.http.HttpServlet ...