题目链接:点击查看

题目大意:给定一个长度为n的数列,依次求m个区间中不相同数字之和

题目分析:n给的是3e4,看到区间问题先要想到线段树或差分区间或动态规划,暴力是肯定不行滴,那么这个题已经知道是需要

用线段树处理了,可是我们只擅长用线段树求区间和,并没有学过求不同数字之和啊,那么该怎么处理重复的数字呢?

这里就要将线段树的两个优势结合起来使用了:单点修改和区间查询

好了,现在来说一下这个题的大体思路,然后在说一下具体实现方法吧:

首先,对于所有的区间查询,我们先采用离线处理的方法,即先将每一个区间都保存起来,记录一下左右端点以及每一个查询的

编号,然后对其右端点进行升序排序,这样可以保证接下来操作的可行性。

接下来我们要依次遍历每个区间,在这个区间内加点,即将点加入线段树中,加点也是有技巧的,我们必须保证相同的数值,只

有在区间中最右边的那个存在,其余位置的这个数字都不能存在,(因为习惯原因,遍历都是从1到n遍历,即从左到右遍历,所

以最右边就是目前最后一个出现的)。综上所述,令加点和查询依次交替进行,并用一个数组存起来,最后依次输出即可。

然后我来讲一下怎么具体实现这些细节:

对于排序,没什么好说的,这个题虽然每个位置的数字范围很大,但是不需要离散化,因为利用下标计算足矣。

然后是如何实现上述加点的过程呢?我们需要一个hash数组来记录每个点最后在线段树中出现的位置,若准备加入的点在以前已

经加入过了,我们只需要将上一个位置的这个点先删除掉,即上一次位置的数字设置为0,然后再加入本次位置的这个点就好

了,然后这个加点的操作可以一直从第一个点维护到区间的右端点,因为维护的过程中保证了线段树中:

  1. 不会出现两个相同数值的点
  2. 从左至右依次进行加点操作
  3. 及时删除掉将会重复的点

这样就可以维护题目中给出的条件了,上代码:

PS:这个题一开始做的时候真的想抽自己,最后输出的ans数组一开始手残写成a数组了,输出的时候怎么输出怎么不对,调试的时候怎么调试怎么没问题,真的服了,看来我真的太弱了

#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<algorithm>
#include<stack>
#include<queue>
#include<map>
#include<sstream>
#include<cmath>
using namespace std;typedef long long LL;const int inf=0x3f3f3f3f;const int N=1e5+100;int a[N];LL ans[N];struct Node
{int l,r;LL sum;
}tree[N<<1];struct node
{int x,y,id;
}p[N];map<int,int>vis;void build(int k,int l,int r)
{tree[k].l=l;tree[k].r=r;tree[k].sum=0;if(l==r)return;int mid=(l+r)>>1;build(k<<1,l,mid);build(k<<1|1,mid+1,r);
}void update(int k,int pos,int val)
{if(tree[k].l==tree[k].r){tree[k].sum=val;return;}int mid=(tree[k].l+tree[k].r)>>1;if(mid>=pos)update(k<<1,pos,val);elseupdate(k<<1|1,pos,val);tree[k].sum=tree[k<<1].sum+tree[k<<1|1].sum;
}LL query(int k,int l,int r)
{if(tree[k].r<l||tree[k].l>r)return 0;if(tree[k].l>=l&&tree[k].r<=r)return tree[k].sum;return query(k<<1,l,r)+query(k<<1|1,l,r);
}bool cmp(node a,node b)
{return a.y<b.y;
}int main()
{
//  freopen("input.txt","r",stdin);int w;cin>>w;while(w--){int n;scanf("%d",&n);build(1,1,n);vis.clear();for(int i=1;i<=n;i++)scanf("%d",a+i);int m;scanf("%d",&m);for(int i=1;i<=m;i++){scanf("%d%d",&p[i].x,&p[i].y);p[i].id=i;}sort(p+1,p+1+m,cmp);int pos=1;for(int i=1;i<=m;i++){while(pos<=p[i].y){if(vis[a[pos]])update(1,vis[a[pos]],0);vis[a[pos]]=pos;update(1,pos,a[pos]);pos++;}
//          cout<<query(1,p[i].x,p[i].y)<<endl;ans[p[i].id]=query(1,p[i].x,p[i].y);
//          cout<<p[i].id<<endl;}for(int i=1;i<=m;i++)cout<<ans[i]<<endl;}return 0;
}

HDU - 3333 Turing Tree(线段树+离线处理)相关推荐

  1. HDU - 3333 Turing Tree 线段树区间不同值和+详解+思想

    传送门 首先第一次做这种求不同元素和的线段树题,猜想是个裸题.但是题目中有一句话显然给题目降低了很大的难度,就是 想想其实它就是在暗示你这道题你要结合多次询问来处理,也就是所谓的离线,而不是一次一次的 ...

  2. HDU 3333 Turing Tree(树状数组+离线处理+离散化)

    题目大意 给一个 n(1≤n≤30000) 个数,数的范围是 0~109.现在给了 Q 个询问,询问的内容是:一个区间 [L, R] 中,所有不同的数的和是多少? 其实和 HDU 3874 一个意思 ...

  3. HDU 3333 Turing Tree(树状数组/主席树)

    题意 给定一个长度为 \(n​\) 的序列,\(m​\) 个查询,每次查询区间 \([L,R]​\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...

  4. HDU 4417 Super Mario(线段树离线处理/主席树)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  5. No Pain No Game HDU - 4630(gcd+线段树+离线处理)

    Life is a game,and you lose it,so you suicide. But you can not kill yourself before you solve this p ...

  6. hdu 3333 Turing Tree 求区间内不同数的和——线段树解法

    http://acm.hdu.edu.cn/showproblem.php?pid=3333 题意:求区间内不同数的和 #include<bits/stdc++.h> using name ...

  7. HDU - 4417 Super Mario(主席树/线段树+离线)

    题目链接:点击查看 题目大意:给出由 n 个数的数列,再给出 m 次查询,每次查询需要输出 [ l , r ] 内小于等于 h 的数有多少个 题目分析:大晚上睡不着觉随便做做题,发现这个题目原来可以用 ...

  8. Super Mario HDU - 4417(主席树解决区间数字小于k的个数||线段树+离线)

    Mario is world-famous plumber. His "burly" figure and amazing jumping ability reminded in ...

  9. SPOJ - DQUERY D-query(莫队/线段树+离线/主席树)

    题目链接:点击查看 题目大意:给出一个由n个数组成的序列,再给出m次查询,每次查询区间[l,r]中有多少个不同的数 题目分析:莫队模板题,直接套板子就好了 有点意思的是函数返回值为布尔类型,然后没有r ...

最新文章

  1. 菜鸟、普通、老鸟程序猿如何写奇数判断?--位操作符妙用
  2. 批量操作WinRAR实用技巧七招
  3. 【学术相关】人工智能顶会审稿现状—理想中的审稿人vs实际审稿人
  4. S/4HANA key user tool创建的Extension field,点了publish后的执行原理
  5. 在社会上闯荡必须要牢记的
  6. Mac版 matlab 安装 GAOT工具箱
  7. java借助Acrobat实现pdf转word
  8. GOOGLE登陆火星
  9. 虚拟机访问本地mysql_本地访问虚拟机oracle数据库的尝试
  10. 地铁在终点站是怎么掉头的?南京地铁怎么过的长江?
  11. 打印机在计算机里被删掉,打印机显示正在删除怎么办 打印机显示正在删除解决办法...
  12. 学习java随堂练习-20220610
  13. GBase 8s灾备集群HAC (三) 主备配置
  14. 如何减少http请求
  15. ITFriend创业败局(一):选择创业方向和寻找合伙人,创业失败的2个关键点
  16. Python之父抛弃Python!现在学Python还有用吗?
  17. 本站视频相关的C++新经典系列书籍出版
  18. 计算机毕业设计asp.net的高校科研项目管理系统(源码+系统+mysql数据库+Lw文档)
  19. latex和latex数学公式
  20. PaintX 瘦脸插件 FCPX插件美颜瘦脸 | 正品序列号

热门文章

  1. MySQL高级 - 存储引擎 - 选择原则
  2. MySQL 高级 - 索引 - 索引语法
  3. Nacos源码InstanceController
  4. Condition.doSignal
  5. JMM中有哪些方法建立happen-before规则
  6. EasyExcel读写Excel的基本使用
  7. MybatisPlus实现自动填充
  8. 模拟spring IOC、源码分析
  9. 通过反射获取成员变量并使用
  10. 使用网络存储SAN和NAS