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 ...
随机推荐
- (转)将cocos2dx项目从VS移植到Eclipse
本文转自:http://www.cnblogs.com/Z-XML/p/3349518.html 引言:我们使用cocos2d-x引擎制作了一款飞行射击游戏,其中创新性地融入了手势识别功能.但是我 们 ...
- python学习之字典
1.字典 列表存储的数据比较单一也不够灵活,这时我们可以使用字典来存储某些多内容的数据,字典是无顺序的 1.简单的字典 book={ 'huqiang':13457412571, 'Jasper':1 ...
- Java开发中经典的小实例-(字符串比较)
//输入字符串然后与自己定义的数组进行对比,并输出重复次数. public class Test11 { public static void main(String[] args) { ...
- 深入浅出设计模式——享元模式(Flyweight Pattern)
模式动机 面向对象技术可以很好地解决一些灵活性或可扩展性问题,但在很多情况下需要在系统中增加类和对象的个数.当对象数量太多时,将导致运行代价过高,带来性能下降等问题.享元模式正是为解决这一类问题而诞生 ...
- 关于C++虚函数的一点点~~
Talk is cheap, show you the code: 1.(普通的) #include<cstdio> class B { public: void func() const ...
- 【Java基础】分支结构(1)
java 分支结构 if , if else , if elseif if /** 文件路径:G:\JavaByHands\if-else\ 文件名称:IfElseT.java 编写时间:2016/6 ...
- JavaEE开发环境搭建(2)---(MySQL的安装)
上次写了JavaEE开发环境搭建之jdk的安装...然后自己看的时候感觉有时候加载图片不是很流畅,所以这次就少添加点图片了~~ JavaEE开发环境搭建之MySQL的安装 1:mysql 的下载 在百 ...
- 转!mysql 查询 distinct多个字段 注意!!
前几天做项目时,mysql写了个sql, distinct id,col1,col2,... 结果出来了多条同个ID的记录,百度了下..... 下面先来看看例子: table id name ...
- CSS 3中边框怎么用
(1)设置边框图片的来源 图片边框默认只在四个顶点显示 none: 无背景图片; border-image-source: url('borderImage.png'); (2)边框图片的分割 将图片 ...
- 经典SQL语句大全以及50个常用的sql语句
经典SQL语句大全 一.基础 1.说明:创建数据库CREATE DATABASE database-name 2.说明:删除数据库drop database dbname3.说明:备份sql serv ...