SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)
题意 : 给出一段n个数的序列,接下来给出m个询问,询问的内容SPOJ是(L, R)这个区间内不同的数的个数,HDU是不同数的和
分析 :
一个经典的问题,思路是将所有问询区间存起来,然后按右端点排序
最后从左到右将原区间扫一遍,扫的过程当中不断将重复出现的数字右移
也就是如果一个数字重复出现,那么我们记录最右边的那个为有效的,其他都视为不存在
这样一旦遇到一个问询区间的右端点就线段树查询即可。
SPOJ:
#include<bits/stdc++.h> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 ; ]; void PushUP(int rt) { sumv[rt] = sumv[rt<<] + sumv[rt<<|]; } void update(int p,int sc,int l,int r,int rt) { if (l == r) { sumv[rt] += sc; return ; } ); if (p <= m) update(p , sc , lson); else update(p , sc , rson); PushUP(rt); } long long query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return sumv[rt]; } ); ; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } struct Interval{ int l, r, id; bool operator < (const Interval& other) const{ return this->r < other.r; } }; Interval sec[]; map<int, int> mp; int arr[maxn]; int pre[maxn]; long long ans[maxn]; int main(void) { , m; scanf("%d", &n); ; i<=n; i++){ scanf("%d", &arr[i]); if(!mp.count(arr[i])) mp[arr[i]] = cnt++;//区间上的每一个数都有一个独特的编号,使用map来进行映射,目的是方便判断此数是否已经重复出现过 } scanf("%d", &m); ; i<=m; i++){ scanf("%d %d", &sec[i].l, &sec[i].r); sec[i].id = i;//因为后续有排序操作,而我们又要对问询答案顺序给出,所以记录给出的顺序,方便输出答案 } sort(sec+, sec++m);//按照右端点排序 bool vis[maxn]; memset(vis, false, sizeof(vis)); , j=; j<=m && i<=n; i++){ int tmp = mp[arr[i]];//拿出这个数的编号 if(vis[tmp]){//如果这个数在前面已经访问过 update(pre[tmp], -, , n, );//将之前的位置信息抹去 update(i, , , n, );//当前的位置才是有效的,所以给当前位置+1 pre[tmp] = i;//更新pre数组方便下次操作 }else{ vis[tmp] = true; update(i, , , n, ); pre[tmp] = i; } while(sec[j].r == i){ ans[sec[j].id] = query(sec[j].l, sec[j].r, , n, ); j++; } } ; i<=m; i++){ printf("%I64d\n", ans[i]); } ; }
HDU:
#include<bits/stdc++.h> using namespace std; #define lson l , m , rt << 1 #define rson m + 1 , r , rt << 1 | 1 ; ]; void PushUP(int rt) { sumv[rt] = sumv[rt<<] + sumv[rt<<|]; } void update(int p,long long sc,int l,int r,int rt) { if (l == r) { sumv[rt] += sc; return ; } ); if (p <= m) update(p , sc , lson); else update(p , sc , rson); PushUP(rt); } long long query(int L,int R,int l,int r,int rt) { if (L <= l && r <= R) { return sumv[rt]; } ); ; if (L <= m) ret += query(L , R , lson); if (R > m) ret += query(L , R , rson); return ret; } struct interval{ int L, R, id; bool operator < (const interval & other) const{ return this->R < other.R; } }; interval sec[maxn<<]; bool vis[maxn]; ]; int per[maxn]; long long arr[maxn]; map<long long, int> mp; int main(void) { int nCase; scanf("%d", &nCase); while(nCase--){ int n; mp.clear(); ; memset(sumv, , sizeof(sumv)); scanf("%d", &n); ; i<=n; i++){ scanf("%I64d", &arr[i]); if(!mp.count(arr[i])) mp[arr[i]] = cnt++; } int m; scanf("%d", &m); ; i<=m; i++){ scanf("%d %d", &sec[i].L, &sec[i].R); sec[i].id = i; } sort(sec+, sec++m); memset(vis, false, sizeof(vis)); , j=; j<=m && i<=n; i++){ int num = mp[arr[i]]; if(vis[num]){ update(per[num],-arr[i],,n,); update(i, arr[i], , n, ); per[num] = i; }else{ vis[num] = true; update(i, arr[i], , n, ); per[num] = i; } while(i==sec[j].R){ ans[sec[j].id] = query(sec[j].L, sec[j].R, , n, ); j++; } } ; i<=m; i++){ printf("%I64d\n", ans[i]); } } }
update in 2018-06-08
学了主席树、以上的离线算法都可以变成在线算法了、戳 主席树
SPOJ D-query && HDU 3333 Turing Tree (线段树 && 区间不相同数个数or和 && 离线处理)的更多相关文章
- HDU 3333 Turing Tree 线段树+离线处理
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Othe ...
- HDU 3333 Turing Tree (线段树)
Turing Tree Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Tota ...
- HDU 3333 Turing Tree(树状数组/主席树)
题意 给定一个长度为 \(n\) 的序列,\(m\) 个查询,每次查询区间 \([L,R]\) 范围内不同元素的和. \(1\leq T \leq 10\) \(1 \leq n\leq 300 ...
- HDU 3333 Turing Tree (主席树)
题意:给定上一个序列,然后有一些询问,求区间 l - r 中有多少个不同的数的和. 析:和求区间不同数的方法是一样,只要用主席树维护就好. 代码如下: #pragma comment(linker, ...
- SPOJ GSS1_Can you answer these queries I(线段树区间合并)
SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...
- W同学的新画板 QDUOJ 线段树 区间颜色段数
W同学的新画板 QDUOJ 线段树 区间颜色段数 原题链接 题意 W同学在每天的刻苦学习完成功课之余,都会去找一些有趣的事情来放松自己:恰巧今天他收到了朋友送给他的一套画板,于是他立刻拆开了包装,拿出 ...
- hdu 3333 Turing Tree 图灵树(线段树 + 二分离散)
http://acm.hdu.edu.cn/showproblem.php?pid=3333 Turing Tree Time Limit: 6000/3000 MS (Java/Others) ...
- hdu 3333 Turing Tree(线段树+离散化)
刚看到是3xian大牛的题就让我菊花一紧,觉着这题肯定各种高端大气上档次,结果果然没让我失望. 刚开始我以为是一个普通的线段树区间求和,然后啪啪啪代码敲完测试没通过,才注意到这个求和是要去掉相同的值的 ...
- HDU 6638 - Snowy Smile 线段树区间合并+暴力枚举
HDU 6638 - Snowy Smile 题意 给你\(n\)个点的坐标\((x,\ y)\)和对应的权值\(w\),让你找到一个矩形,使这个矩阵里面点的权值总和最大. 思路 先离散化纵坐标\(y ...
随机推荐
- python 并发编程 socket 服务端 客户端 阻塞io行为
阻塞io行为 server.accept server.recv client.send recv,accept 分为两个阶段 1.wait for data 对方把数据经过网络延迟送到自己的操作系 ...
- Luogu P2839 [国家集训队]middle
题目 首先我们考虑解决中位数一类问题的常用手段:二分\(mid\),将大于等于它的设为\(1\),小于它的设为\(−1\),判断区间和是否\(\ge0\). 对于询问\(a,b,c,d\),二分完\( ...
- Oracle及SQLPLUS使用笔记
Oracle及SQLPLUS使用笔记 自己之前粗粗的学过MySQL,学校用的是Oracle,学生使用sqlplus,这是个命令行界面的数据库管理软件(为了学习嘛,不用图形化可以理解),这里记录一些使用 ...
- docker Dockerfile文件的编写部分命令
镜像的构建过程:编写dockerfile文件,执行docker build 进行构建镜像,最后docker run 运行容器镜像实例. docker build -t mycentos:1.01 . ...
- vue-Ie下踩坑20190820
开发的vue项目终于告一段落,终于是可以部署在测试服务器给客户看了,期间也是遇到各式各样的坑. 1.有些bug在谷歌是在没问题的,在ie上就会暴露出来,因为其中一个模块设计多个类型资源的列表,所以写纯 ...
- 如何将本地的一个新项目上传到GitHub上新建的仓库中去
1:我们需要先创建一个本地的版本库(其实也就是一个文件夹).直接右击新建文件夹,或者右击打开Git bash命令行窗口通过命令mkdir来创建(mkdir 文件名). 进入这个文件夹的根目录,选中目录 ...
- JS判断页面是否为浏览器当前页
function currentPage() { var hiddenProperty = 'hidden' in document ? 'hidden' : 'webkitHidden' in do ...
- wpf Textbox 回车就换行
将 TextWrapping 属性设置为 Wrap 会导致输入的文本在到达 TextBox 控件的边缘时换至新行,必要时会自动扩展 TextBox 控件以便为新行留出空间. 将 AcceptsRetu ...
- nodejs 常用插件
.circular-json npm install circular-json JSON.parse高级版 .cookie-parser .md5-node .multer 上传插件 .npm i ...
- softmax+交叉熵
1 softmax函数 softmax函数的定义为 $$softmax(x)=\frac{e^{x_i}}{\sum_j e^{x_j}} \tag{1}$$ softmax函数的特点有 函数值在[0 ...