Turing Tree_线段树&树状数组
Now given a sequence of N numbers A1, A2, ..., AN and a number of Queries(i, j) (1≤i≤j≤N). For each Query(i, j), you are to caculate the sum of distinct values in the subsequence Ai, Ai+1, ..., Aj.
For each case, the input format will be like this:
* Line 1: N (1 ≤ N ≤ 30,000).
* Line 2: N integers A1, A2, ..., AN (0 ≤ Ai ≤ 1,000,000,000).
* Line 3: Q (1 ≤ Q ≤ 100,000), the number of Queries.
* Next Q lines: each line contains 2 integers i, j representing a Query (1 ≤ i ≤ j ≤ N).
3
1 1 4
2
1 2
2 3
5
1 1 2 1 3
3
1 5
2 4
3 5
5
6
3
6
【题意】给出n个数,然后提出m个问题,求区间内不重复的数之和。
【思路】先按查询的右坐标升序排列(保证我查询的改动不会影响到后面查询的结果)。把每个数放进线段树的时候,先判断再之前他有没有在线段树,如果在,则删除它,并把他的位置更新到当前点。
线段树:
#include<iostream>
#include<stdio.h>
#include<map>
#include<string.h>
#include<algorithm>
using namespace std;
typedef long long int LL;
const int N=+;
const int M=+;
int n,m;
struct node1
{
int l,r;
LL num; }sum[N*];
struct node
{
int ll,rr,index; }q[M];
bool cmp(node x,node y)//按他的右边界排序
{
return x.rr<y.rr;
}
LL a[N];
map<LL,int>mp;//记录是否出现过相同的数,如果有记录位置
LL ans[M];
void build(int k,int l,int r)//建树
{
sum[k].l=l;
sum[k].r=r;
sum[k].num=;
if(l==r) return ;
int mid=l+r>>;
build(k*,l,mid);
build(k*+,mid+,r);
}
void update(int k,int l,int r,int x,LL v)//更新结点的值
{
if(l==r)
{
sum[k].num+=v;
return ;
}
int mid=l+r>>;
if(x<=mid) update(k*,l,mid,x,v);
else update(k*+,mid+,r,x,v);
sum[k].num=sum[k*].num+sum[k*+].num;
}
LL query(int k,int l,int r,int ll,int rr)//查询区间的值
{
if(l>=ll&&r<=rr)
{
return sum[k].num;
}
int mid=l+r>>;
LL res=;
if(ll<=mid) res+=query(k*,l,mid,ll,rr);
if(rr>mid) res+=query(k*+,mid+,r,ll,rr);
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%I64d",&a[i]);
}
build(,,n);
scanf("%d",&m);
for(int i=;i<m;i++)
{
scanf("%d%d",&q[i].ll,&q[i].rr);
q[i].index=i;
}
sort(q,q+m,cmp);
int k=;
for(int i=;i<m;i++)
{
for(;k<=q[i].rr;k++)
{
if(mp[a[k]]!=) update(,,n,mp[a[k]],-a[k]);//如果曾经出现过,则将以前的结点删去
mp[a[k]]=k;//将位置赋给当前的结点
update(,,n,k,a[k]);//将当前结点更新到树中
}
ans[q[i].index]=query(,,n,q[i].ll,q[i].rr);
}
for(int i=;i<m;i++) printf("%I64d\n",ans[i]);
}
return ;
}
树状数组:
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
using namespace std;
const int N=+;
int n,m,a[N];
long long sum[N*],ans[N*];
map<int,int >mp;
struct node
{
int l,r,id;
bool operator<(const node &a)const{
if(r==a.r) return l<a.l;
return r<a.r;
}
}q[N*];
int lowbit(int x)
{
return x&(-x);
}
void update(int p,int v)
{
while(p<=n)
{
sum[p]+=v;
p+=lowbit(p);
}
}
long long int query(int p)
{
long long int res=;
while(p)
{
res+=sum[p];
p-=lowbit(p);
}
return res;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
mp.clear();
memset(sum,,sizeof(sum));
scanf("%d",&n);
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
}
scanf("%d",&m);
for(int i=;i<m;i++)
{
int l,r;
scanf("%d%d",&l,&r);
q[i].l=l;q[i].r=r;q[i].id=i;
}
sort(q,q+m);
int cnt=;
for(int i=;i<=n;i++)
{
if(mp.find(a[i])==mp.end())//在mp中没有找到
{
update(i,a[i]);
mp[a[i]]=i;
}
else
{
update(i,a[i]);
update(mp[a[i]],-a[i]);
mp[a[i]]=i;
}
while(q[cnt].r==i)
{
ans[q[cnt].id]=query(q[cnt].r)-query(q[cnt].l-);
cnt++;
}
}
for(int i=;i<m;i++) printf("%lld\n",ans[i]);
}
return ;
}
Turing Tree_线段树&树状数组的更多相关文章
- CodeForces -163E :e-Government (AC自动机+DFS序+树状数组)
The best programmers of Embezzland compete to develop a part of the project called "e-Governmen ...
- HDU 3333 Turing Tree 离线 线段树/树状数组 区间求和单点修改
题意: 给一个数列,一些询问,问你$[l,r]$之间不同的数字之和 题解: 11年多校的题,现在属于"人尽皆知傻逼题" 核心思想在于: 对于一个询问$[x,R]$ 无论$x$是什么 ...
- Hdu-3333 Turning Tree (离线树状数组/线段树)
Hdu-3333 Turning Tree 题目大意:先给出n个数字.面对q个询问区间,输出这个区间不同数的和. 题解:这道题有多重解法.我另一篇博客写了分块的解法 HDU-3333 Turing ...
- [bzoj1901][zoj2112][Dynamic Rankings] (整体二分+树状数组 or 动态开点线段树 or 主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- HDU 1556 线段树或树状数组,插段求点
1.HDU 1556 Color the ball 区间更新,单点查询 2.题意:n个气球,每次给(a,b)区间的气球涂一次色,问最后每个气球各涂了几次. (1)树状数组 总结:树状数组是一个查 ...
- HDU 3966 Aragorn's Story 树链剖分+树状数组 或 树链剖分+线段树
HDU 3966 Aragorn's Story 先把树剖成链,然后用树状数组维护: 讲真,研究了好久,还是没明白 树状数组这样实现"区间更新+单点查询"的原理... 神奇... ...
- 【树状数组套权值线段树】bzoj1901 Zju2112 Dynamic Rankings
谁再管这玩意叫树状数组套主席树我跟谁急 明明就是树状数组的每个结点维护一棵动态开结点的权值线段树而已 好吧,其实只有一个指针,指向该结点的权值线段树的当前结点 每次查询之前,要让指针指向根结点 不同结 ...
- HDU 1394 Minimum Inversion Number(最小逆序数/暴力 线段树 树状数组 归并排序)
题目链接: 传送门 Minimum Inversion Number Time Limit: 1000MS Memory Limit: 32768 K Description The inve ...
- POJ 2299 Ultra-QuickSort 逆序数 树状数组 归并排序 线段树
题目链接:http://poj.org/problem?id=2299 求逆序数的经典题,求逆序数可用树状数组,归并排序,线段树求解,本文给出树状数组,归并排序,线段树的解法. 归并排序: #incl ...
随机推荐
- [问题2015S12] 复旦高等代数 II(14级)每周一题(第十三教学周)
[问题2015S12] 设 \(A\) 为 \(n\) 阶实矩阵, 若对任意的非零 \(n\) 维实列向量 \(\alpha\), 总有 \(\alpha'A\alpha>0\), 则称 \( ...
- CentOs 设置静态IP 方法
在做项目时由于局域网采用自动获取IP的方式,导到每次服务器重启主机IP都会变化. 为了解决这个问题,需要设置静态IP. 1.修改网卡配置 编辑:vi /etc/sysconfig/network-sc ...
- Android 自动化测试 Emmagee
Emmagee 是一个性能测试小工具 用来监控指定被测应用在使用过程中占用机器的CPU, 内存,流量资源的性能小工具 阅读目录 Emmagee 介绍 Emmagee是网易杭州研究院QA团队开发的一个简 ...
- 安装numpy+mkl
引子: 运行from sklearn.dataset import load_iris 时提示: Traceback (most recent call last): File "F:/gi ...
- [java基础]分支结构(2)
[java基础]分支结构2 switch case /** 文件路径:G:\JavaByHands\if-else\ 文件名称:switchcase.java 编写时间:2016/6/6 作 者:郑晨 ...
- Java 序列化 反序列化 历史版本处理
直接引用 http://www.cnblogs.com/xdp-gacl/p/3777987.html
- python的类和对象——进阶篇
写在前面的话 终于,又到了周五.当小伙伴们都不再加班欢欢喜喜过周末的时候,我刚刚写完这一周的游戏作业,从面对晚归的紧皱眉头到现在的从容淡定,好像只有那么几周的时间.突然发现:改变——原来这么简单.很多 ...
- 将Python脚本封装成exe可执行文件 转
将Python脚本封装成exe可执行文件 http://www.cnblogs.com/renzo/archive/2012/01/01/2309260.html cx_freeze是用来将 Pyt ...
- sanBox部署简介
参考资料:1 http://www.kaaproject.org/getting-started/ 此链接告诉我们部署sandbox的两种方法. 2 http://docs.kaaprojec ...
- 项目二(业务GO)——跨域上传图片(请求接口)
之前,就听过“跨域上传”图片的问题,只是疏于研究,也就一再搁置,直至今天再次遇见这个不能避免的“坑”,才不得不思考一下,怎么“跨域上传”图片或者文件? 问题来源: 何为“跨域”? ——就是给你一个接口 ...